BZOJ4378[POI2015]Logistyka 树状数组
Posted CQzhangyu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ4378[POI2015]Logistyka 树状数组相关的知识,希望对你有一定的参考价值。
【BZOJ4378】[POI2015]Logistyka
Description
维护一个长度为n的序列,一开始都是0,支持以下两种操作:
1.U k a 将序列中第k个数修改为a。
2.Z c s 在这个序列上,每次选出c个正数,并将它们都减去1,询问能否进行s次操作。
每次询问独立,即每次询问不会对序列进行修改。
Input
第一行包含两个正整数n,m(1<=n,m<=1000000),分别表示序列长度和操作次数。
接下来m行为m个操作,其中1<=k,c<=n,0<=a<=10^9,1<=s<=10^9。
Output
包含若干行,对于每个Z询问,若可行,输出TAK,否则输出NIE。
Sample Input
3 8
U 1 5
U 2 7
Z 2 6
U 3 1
Z 2 6
U 2 2
Z 2 6
Z 2 1
U 1 5
U 2 7
Z 2 6
U 3 1
Z 2 6
U 2 2
Z 2 6
Z 2 1
Sample Output
NIE
TAK
NIE
TAK
TAK
NIE
TAK
题解:我们考虑什么情况下询问有解。若一个数>s,那么我们肯定贪心的每次都让它-1,但是它最多只能取s次,所以它跟s没什么区别;若一个数≤s,那我们贪心的将它取到0,它对总和的贡献就是它本身。所以综上所述,有解的条件就是 ∑min(v[i],s) (1≤i≤n)≥c*s。我们只需要维护两个树状数组,一个记录>s的数的个数,一个记录≤s的数的总和,然后只要 个数*s+总和≥c*s就行了
需要离散化,别忘开long long
#include <cstdio> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; const int maxn=1000010; int n,m,nm; char str[5]; struct node { int org; ll num; }p[maxn<<1]; int qa[maxn],qc[maxn]; ll ref[maxn<<1],s1[maxn],s2[maxn],v[maxn],qb[maxn]; int rd() { int ret=0,f=1; char gc=getchar(); while(gc<‘0‘||gc>‘9‘) {if(gc==‘-‘)f=-f; gc=getchar();} while(gc>=‘0‘&&gc<=‘9‘) ret=ret*10+gc-‘0‘,gc=getchar(); return ret*f; } void up1(int x,ll val) { for(int i=x;i<=nm;i+=i&-i) s1[i]+=val; } void up2(int x,ll val) { for(int i=x;i<=nm;i+=i&-i) s2[i]+=val; } ll q1(int x) { int i=x; ll ret=0; for(i=x;i;i-=i&-i) ret+=s1[i]; return ret; } ll q2(int x) { int i=x; ll ret=0; for(i=x;i;i-=i&-i) ret+=s2[i]; return ret; } bool cmp(node a,node b) { return a.num<b.num; } int main() { n=rd(),m=rd(); int i,j,a,b; for(i=1;i<=m;i++) { scanf("%s",str),qa[i]=rd(),p[i].num=rd(),p[i].org=i; if(str[0]==‘U‘) qc[i]=0; else qc[i]=1; } sort(p+1,p+m+1,cmp); ref[1]=0,nm=1; for(i=1;i<=m;i++) { if(p[i].num>ref[nm]) ref[++nm]=p[i].num; qb[p[i].org]=nm; } for(i=1;i<=n;i++) up1(1,1),v[i]=1; for(i=1;i<=m;i++) { if(!qc[i]) { up1(v[qa[i]],-1),up2(v[qa[i]],-ref[v[qa[i]]]),v[qa[i]]=qb[i]; up1(qb[i],1),up2(qb[i],ref[qb[i]]); } else { if((n-q1(qb[i]))*ref[qb[i]]+q2(qb[i])>=qa[i]*ref[qb[i]]) printf("TAK\n"); else printf("NIE\n"); } } return 0; }
以上是关于BZOJ4378[POI2015]Logistyka 树状数组的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ_4378_[POI2015]Logistyka_树状数组