bzoj4444: [Scoi2015]国旗计划
流年不利啊最近。。。要么就是要了数据只WA一个点。。。要么就是WA成一片还是一个一个点调对。。。
这题很明显就是贪心了,离线后按l排序(记得要复制一份放在后面,对于环这是常规操作了吧),由于没有覆盖,对于一个l~r的区间,下一个接棒的左端点一定是最接近右边界的,可以预处理出来,最后用倍增的思想出解。
一开始打了个沙茶的玄学复杂度dfs是什么鬼。。
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; int n,m; struct query { int l,r,id; friend bool operator <(query q1,query q2){return q1.l<q2.l;} }q[410000];int qlen; void qins(int l,int r,int id) { qlen++; q[qlen].l=l;q[qlen].r=r;q[qlen].id=id; } int f[30][410000]; int as[410000]; int main() { freopen("flag.in","r",stdin); freopen("flag.out","w",stdout); scanf("%d%d",&n,&m); qlen=0; for(int i=1;i<=n;i++) { int x,y; scanf("%d%d",&x,&y); if(x>y)y+=m; qins(x,y,i); qins(x+m,y+m,0); } sort(q+1,q+qlen+1); memset(f,0,sizeof(f)); for(int i=1;i<=qlen;i++) { query tt;tt.l=q[i].r; f[0][i]=upper_bound(q+1,q+qlen+1,tt)-q-1; if(f[0][i]==i)f[0][i]=0; } for(int i=qlen;i>=1;i--) { for(int j=1;f[j-1][f[j-1][i]]!=0;j++) f[j][i]=f[j-1][f[j-1][i]]; } for(int i=1;i<=qlen;i++) { if(q[i].id>0) { as[q[i].id]=0; int now=i; for(int j=25;j>=0;j--) if(f[j][now]>0&&q[f[j][now]].r-q[i].l<m) as[q[i].id]+=(1<<j), now=f[j][now]; as[q[i].id]++; } } for(int i=1;i<n;i++)printf("%d ",as[i]+1); printf("%d\n",as[n]+1); return 0; }
pain and happy in the cruel world.