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

Sample Output

NIE
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
");
            else printf("NIE
");
        }
    }
    return 0;
}
View Code