bzoj 4378: [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
————————————————————————————
这道题离散化一下值 维护一下两个树桩数组 一个维护后缀个数 一个维护前缀和就可以了
#include<cstdio> #include<cstring> #include<algorithm> #define LL long long const int M=2e6+7; using std::sort; using std::unique; using std::lower_bound; int read(){ int ans=0,f=1,c=getchar(); while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();} return ans*f; } int n,m; char c[M][3]; struct pos{LL x,w,s;}q[M]; int x[M],cnt,v[M],last[M]; LL s[M],w[M];//sÊÇÇóÓжàÉÙ¸öÊý±ÈÎҴ󣨺ó׺£© wÊÇÇó±ÈÎÒСµÄÊýµÄºÍ£¨Ç°×º£© #define lowbit(x) x&-x void ins_s(int x,int v){while(x) s[x]+=v,x-=lowbit(x);} LL query_s(int x){LL sum=0; while(x<=cnt) sum+=s[x],x+=lowbit(x); return sum;} void ins_w(int x,int v){while(x<=cnt) w[x]+=v,x+=lowbit(x);} LL query_w(int x){LL sum=0; while(x) sum+=w[x],x-=lowbit(x); return sum;} int main(){ n=read(); m=read(); for(int i=1;i<=m;i++){ scanf("%s",c[i]); q[i].x=read(); q[i].w=read(); x[++cnt]=q[i].w; } sort(x+1,x+1+cnt); cnt=unique(x+1,x+1+cnt)-x-1; for(int i=1;i<=m;i++) q[i].s=lower_bound(x+1,x+1+cnt,q[i].w)-x; for(int i=1;i<=m;i++){ if(c[i][0]=='U'){ if(last[q[i].x]) ins_s(last[q[i].x],-1),ins_w(last[q[i].x],-v[q[i].x]); last[q[i].x]=q[i].s; v[q[i].x]=q[i].w; ins_s(last[q[i].x],1); ins_w(last[q[i].x],v[q[i].x]); } else{ LL ly=0,k=query_s(q[i].s); if(q[i].s-1>0) ly=query_w(q[i].s-1); if((q[i].x-k)*q[i].w<=ly) printf("TAK\n"); else printf("NIE\n"); } } return 0; }