bzoj2527 [Poi2011]Meteors
这个题是在GYZ冬令营讲课课件里翻出来的,所以我一开始使劲地往分治上去想,良久,无果··········
题意是给你一圈位置,位置上有若干颜色(可以重复),每个颜色有一个需求量,每一个时间给一个段加上一个数,最后问每个颜色最早加到需求量的时间。
今天早晨睡觉起来(大概是10点多),赖在床上,YY这个题,突然想到整体二分然后计算贡献似乎非常不错。但是对于序列的处理怎么搞才能把复杂度降下来呢?于是我想到用链表记录每个颜色的位置,这样计算均摊下来就是O(m)了,用树状数组处理,外面套一个整体二分,似乎是非常不错。(但我不知道这算不算与序列长度线性相关了,XHR论文里不是说必须跟询问长线性相关吗?)
整理一下思路,我们二分答案(修改操作的标号),对于[L,R]这一次分治,我们令[L,MID]这些修改操作生效,然后计算每一个询问(1..n个位置),如果求得各个位置的和大于需求,那么将这个询问划分到左区间,否则将各个位置的和累加到贡献上,将询问划分到右区间,整体二分的思路,一气呵成!
对于NIE情况的处理,可以在最后加一个给所有数加上1e9+1,这样如果计算到的答案是Q+1的话输出NIE。
meteors
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #define maxn 301000 7 #define inf 100000000000ll 8 using namespace std; 9 struct query 10 { 11 int pos; 12 long long cur,ned; 13 }q[maxn],q1[maxn],q2[maxn]; 14 struct adj 15 { 16 int l,r; 17 long long s; 18 }c[maxn]; 19 int ans[maxn],fir[maxn],last[maxn],next[maxn]; 20 int n,m,p; 21 struct bit 22 { 23 long long b[maxn]; 24 void add(int x,long long z) 25 { 26 for (int i=x;i<=m;i+=(i&-i)) b[i]+=z; 27 } 28 long long ask(int x) 29 { 30 long long tmp=0; 31 for (int i=x;i;i-=(i&-i)) tmp+=b[i]; 32 return tmp; 33 } 34 }s; 35 36 void adjust(int l,int r,long long z) 37 { 38 s.add(l,z); s.add(r+1,-z); 39 } 40 41 long long query(int x) 42 { 43 return s.ask(x); 44 } 45 46 void solve(int l,int r,int head,int tail) 47 { 48 if (head>tail) return ; 49 if (l==r) 50 { 51 for (int i=head;i<=tail;i++) 52 ans[q[i].pos]=l; 53 return ; 54 } 55 int mid=(l+r)/2,t1=0,t2=0; 56 for (int i=l;i<=mid;i++) 57 if (c[i].l<=c[i].r) adjust(c[i].l,c[i].r,c[i].s); 58 else adjust(c[i].l,m,c[i].s),adjust(1,c[i].r,c[i].s); 59 for (int i=head;i<=tail;i++) 60 { 61 long long tmp=0; 62 for (int j=fir[q[i].pos];j&&tmp<=inf;j=next[j]) 63 tmp+=query(j); 64 if (q[i].cur+tmp>=q[i].ned) 65 q1[++t1]=q[i]; 66 else 67 { 68 q[i].cur+=tmp; 69 q2[++t2]=q[i]; 70 } 71 } 72 for (int i=l;i<=mid;i++) 73 if (c[i].l<=c[i].r) adjust(c[i].l,c[i].r,-c[i].s); 74 else adjust(c[i].l,m,-c[i].s),adjust(1,c[i].r,-c[i].s); 75 for (int i=1;i<=t1;i++) q[head+i-1]=q1[i]; 76 for (int i=1;i<=t2;i++) q[head+t1+i-1]=q2[i]; 77 solve(l,mid,head,head+t1-1); 78 solve(mid+1,r,head+t1,tail); 79 } 80 81 int main() 82 { 83 //freopen("meteors.in","r",stdin); 84 scanf("%d%d",&n,&m); 85 int a; 86 for (int i=1;i<=m;i++) 87 { 88 scanf("%d",&a); 89 if (!fir[a]) fir[a]=i; 90 next[last[a]]=i; 91 last[a]=i; 92 } 93 for (int i=1;i<=n;i++) 94 { 95 scanf("%d",&q[i].ned); 96 q[i].pos=i; q[i].cur=0; 97 } 98 scanf("%d",&p); 99 for (int i=1;i<=p;i++) 100 scanf("%d%d%d",&c[i].l,&c[i].r,&c[i].s); 101 c[++p].l=1; c[p].r=m; c[p].s=1000000010; 102 solve(1,p,1,n); 103 for (int i=1;i<=n;i++) 104 if (ans[i]==p) printf("NIE\n"); 105 else printf("%d\n",ans[i]); 106 return 0; 107 }
AC without art, no better than WA !