嘴巴选手真爽,一不用打代码二不用掉Rating三还可以打杂。。。。
感觉这套题不难,但是被出题人出瞎了。。。
555A. Case of Matryoshkas
题目大意:给定n个大小从1到n的套娃,初始套成k坨,每次你可以选择两个操作:
1.选择一个不在任何其他套娃里的套娃,将里面的套娃取出来(要求原先里面有套娃)
2.选择一个不再任何其他套娃里的套娃,将一个套娃塞进去(要求原先里面没有套娃)
求将所有套娃合并的最小操作次数
如果一个套娃x初始在最里面,或者满足大小为1...x?1的套娃都在它里面,那么这个套娃可以不用拆开
将所有需要拆开的套娃拆开,然后一一合并
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 100100
using namespace std;
int n,m,k,cnt,ans;
int main()
{
int i,j,x,last;
cin>>n>>k;
for(i=1;i<=k;i++)
{
bool flag=false;
scanf("%d",&m);
for(j=1;j<=m;j++)
{
scanf("%d",&x);
if(j>1)
++ans;
if(flag&&x==last+1)
--ans;
else
++cnt,flag=false;
if(x==1)
flag=true;
last=x;
}
}
cout<<ans+cnt-1<<endl;
return 0;
}
555B. Case of Fugitive
题目大意:给定n个岛,第i个岛可以用一个区间[li,ri]表示,满足对于任意1≤i<n有ri<li+1
现在需要将每两个相邻的岛之间架一座桥,桥的长度需要在[li+1?ri,ri+1?li]之间
给定m块木板,问是否能完成任务
问题可以简化为给定n?1个区间和m个点问是否存在一个匹配满足每个点都在对应区间内且所有区间都被匹配上
将区间按左端点从大到小排序,依次扫描
每次扫描到一个区间,将所有大于等于区间左端点的点都扔进set,然后取走所有小于等于区间右端点的点中最大的那个,不存在则无解
#include <set>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 200200
using namespace std;
struct Interval{
long long l,r,id;
bool operator < (const Interval &i) const
{
return l < i.l ;
}
}intervals[M];
int n,m,ans[M];
set< pair<long long,int> > s;
pair<long long,int> points[M];
int main()
{
int i,j;
long long _l,_r,l,r;
cin>>n>>m>>_l>>_r;n--;
for(i=1;i<=n;i++)
{
scanf("%I64d%I64d",&l,&r);
intervals[i].l=l-_r;
intervals[i].r=r-_l;
intervals[i].id=i;
_l=l;_r=r;
}
for(i=1;i<=m;i++)
{
scanf("%I64d",&points[i].first);
points[i].second=i;
}
sort(intervals+1,intervals+n+1);
sort(points+1,points+m+1);
for(j=m,i=n;i;i--)
{
for(;j&&points[j].first>=intervals[i].l;j--)
s.insert(points[j]);
set< pair<long long,int> >::iterator it=s.upper_bound(make_pair(intervals[i].r+1,0));
if(it==s.begin())
return puts("No"),0;
--it;ans[intervals[i].id]=it->second;s.erase(it);
}
puts("Yes");
for(i=1;i<=n;i++)
printf("%d%c",ans[i],i==n?‘\n‘:‘ ‘);
return 0;
}
555C. Case of Chocolate
题目大意:给定一个n?n的巧克力,初始啃掉副对角线右下方的区域,然后每次选择副对角线上的一个位置,然后选择一个方向(上/左),一路啃下去,直到啃到一个空的位置为止,输出啃掉的长度
每啃一次会把当前啃到的块分成至多两小块
当前剩下的每一块巧克力可以用一个四元组(l,r,left_bound,up_bound)表示,其中l和r表示副对角线上的区间,left_bound表示左边界,up_bound表示上边界
每次啃的时候去set上找啃到哪块即可
#include <set>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
struct abcd{
int l,r;
int left_bound,up_bound;
abcd() {}
abcd(int _,int __,int ___,int ____):
l(_),r(__),left_bound(___),up_bound(____) {}
bool operator < (const abcd &a) const
{
return r < a.r ;
}
};
int n,q;
set<int> v;
set<abcd> s;
int main()
{
int i,x,y;
char p[10];
cin>>n>>q;
s.insert(abcd(1,n,1,1));
for(i=1;i<=q;i++)
{
scanf("%d%d%s",&y,&x,p);
if(v.find(y)!=v.end())
{
puts("0");
continue;
}
v.insert(y);
set<abcd>::iterator it=s.lower_bound(abcd(0,y,0,0));
abcd temp=*it;s.erase(it);
if(p[0]==‘U‘)
{
printf("%d\n",x-temp.up_bound+1);
s.insert(abcd(temp.l,y-1,temp.left_bound,temp.up_bound));
s.insert(abcd(y+1,temp.r,y+1,temp.up_bound));
}
else
{
printf("%d\n",y-temp.left_bound+1);
s.insert(abcd(temp.l,y-1,temp.left_bound,x+1));
s.insert(abcd(y+1,temp.r,temp.left_bound,temp.up_bound));
}
}
return 0;
}
555D. Case of a Top Secret
题目大意:给定n个挂点,m个重锤,第i个重锤初始挂在第ai个挂点上,挂绳长度为leni,初始向右摆动,刮到一个重锤后会折返,问最后挂在哪个重锤上
每次二分找位置,记录路径,如果是A?A?A就输出答案,如果是A?B?A就取模,这样不超过log2len次挂绳的长度就会变为0
复杂度O(m?log2n?log2len)
注意初始给出的挂点不一定按顺序,注意挂点的标号不是排序后的标号。。。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 200200
using namespace std;
int n,m;
int a[M],b[M],id[M];
//id[i]=j表示排序后的第i个是排序前的第j个
int stack[1001001],top;
int main()
{
int i,pos,len;
cin>>n>>m;
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
memcpy(b+1,a+1,sizeof(a[0])*n);
sort(a+1,a+n+1);
for(i=1;i<=n;i++)
id[lower_bound(a+1,a+n+1,b[i])-a]=i;
for(i=1;i<=m;i++)
{
scanf("%d%d",&pos,&len);
pos=lower_bound(a+1,a+n+1,b[pos])-a;
stack[top=1]=pos;
while(1)
{
if( top>=3 && stack[top]==stack[top-1] && stack[top]==stack[top-2] )
{
printf("%d\n",id[stack[top]]);
break;
}
if( top>=3 && stack[top]==stack[top-2] )
len%=abs(a[stack[top]]-a[stack[top-1]])<<1;
int next_pos;
if(top&1)
next_pos=upper_bound(a+1,a+n+1,a[pos]+len)-a-1;
else
next_pos=lower_bound(a+1,a+n+1,a[pos]-len)-a;
len-=abs(a[pos]-a[next_pos]);
pos=next_pos;stack[++top]=pos;
}
}
return 0;
}
555E. Case of Computer Network
题目大意:给定一张无向图,要求有向化,使得有向化之后si可以到达ti
一个边双有向化之后可以变成一个强连通分量
缩边双后剩下一座森林,每条边只能被指定一个方向,DFS一遍判断即可
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 200200
using namespace std;
struct edge{
int x,y;
}edges[M];
struct abcd{
int to,next;
}table[M<<1];
int head[M],tot=1;
int n,m,q,cnt;
int belong[M],dpt[M],fa[M][18];
int mark1[M],mark2[M];
void Add(int x,int y)
{
table[++tot].to=y;
table[tot].next=head[x];
head[x]=tot;
}
void Tarjan(int x,int from)
{
static int dpt[M],low[M],T;
static int stack[M],top;
int i;
dpt[x]=low[x]=++T;
stack[++top]=x;
for(i=head[x];i;i=table[i].next)
if(i^from^1)
{
if(dpt[table[i].to])
low[x]=min(low[x],dpt[table[i].to]);
else
Tarjan(table[i].to,i),low[x]=min(low[x],low[table[i].to]);
}
if(dpt[x]==low[x])
{
int t;++cnt;
do{
t=stack[top--];
belong[t]=cnt;
}while(t!=x);
}
}
namespace Union_Find_Set{
int fa[M],rank[M];
int Find(int x)
{
if(!fa[x]||fa[x]==x)
return fa[x]=x;
return fa[x]=Find(fa[x]);
}
void Union(int x,int y)
{
x=Find(x);y=Find(y);
if(x==y) return ;
if(rank[x]>rank[y])
swap(x,y);
if(rank[x]==rank[y])
++rank[y];
fa[x]=y;
}
}
void DFS1(int x)
{
int i;
dpt[x]=dpt[fa[x][0]]+1;
for(i=1;i<=17;i++)
fa[x][i]=fa[fa[x][i-1]][i-1];
for(i=head[x];i;i=table[i].next)
if(table[i].to!=fa[x][0])
{
fa[table[i].to][0]=x;
DFS1(table[i].to);
}
}
int LCA(int x,int y)
{
int j;
if(dpt[x]<dpt[y])
swap(x,y);
for(j=17;~j;j--)
if(dpt[fa[x][j]]>=dpt[y])
x=fa[x][j];
if(x==y) return x;
for(j=17;~j;j--)
if(fa[x][j]!=fa[y][j])
x=fa[x][j],y=fa[y][j];
return fa[x][0];
}
void DFS2(int x)
{
int i;
for(i=head[x];i;i=table[i].next)
if(table[i].to!=fa[x][0])
{
DFS2(table[i].to);
mark1[x]+=mark1[table[i].to];
mark2[x]+=mark2[table[i].to];
}
if(mark1[x]&&mark2[x])
exit((puts("No"),0));
}
int main()
{
using namespace Union_Find_Set;
int i,x,y;
cin>>n>>m>>q;
for(i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
edges[i].x=x;
edges[i].y=y;
Add(x,y);Add(y,x);
}
for(i=1;i<=n;i++)
if(!belong[i])
Tarjan(i,0);
memset(head,0,sizeof head);tot=0;
for(i=1;i<=m;i++)
{
x=belong[edges[i].x];
y=belong[edges[i].y];
if(x!=y)
Add(x,y),Add(y,x),Union(x,y);
}
for(i=1;i<=cnt;i++)
if(i==Find(i))
DFS1(i);
for(i=1;i<=q;i++)
{
scanf("%d%d",&x,&y);
x=belong[x];
y=belong[y];
if(Find(x)!=Find(y))
return puts("No"),0;
int lca=LCA(x,y);
mark1[x]++;mark2[y]++;
mark1[lca]--;mark2[lca]--;
}
for(i=1;i<=n;i++)
if(i==Find(i))
DFS2(i);
puts("Yes");
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。