BZOJ 3343 魔法

  我们注意到q很小,每次询问的区间最多被之前的修改划分成O(q)个区间,我们把每个区间放到主席树上查询。

 

#pragma GCC optimize("-Ofast")
#include<bits/stdc++.h>
#define fi first
#define se second
#define N 11000007//|||
#define Q 6007
#define Max(a,b) (a>b?a:b)
#define Min(a,b) (a<b?a:b) 
#define Mid (l+r>>1)
using namespace std;
int n,q,x,ls[N],rs[N],key[N],rt[N/10],cnt,l[Q],r[Q],w[Q],L,R,tot,C,ans;
long long sum;
char ch[4];
map<int,int> mp;
map<int,int>:: iterator it,la;
void add(int last,int &now,int l,int r,int pos){
    now=++cnt; key[now]=key[last]+1; if (l==r) return;
    if (pos<=Mid) rs[now]=rs[last],add(ls[last],ls[now],l,Mid,pos);
    else ls[now]=ls[last],add(rs[last],rs[now],Mid+1,r,pos);
}
int que(int now,int l,int r,int pos){
    if (l==r) return key[now];
    if (pos<=Mid) return key[rs[now]]+que(ls[now],l,Mid,pos);
    return que(rs[now],Mid+1,r,pos);
}
inline void read(int &x){
    static char c;
    for (c=getchar();!isdigit(c);c=getchar());
    for (x=0;isdigit(c);c=getchar())x=x*10+c-48;
}
void write(int x){if (x<10) {putchar('0'+x); return;} write(x/10); putchar('0'+x%10);}
inline void writeln(int x){ if (x<0) putchar('-'),x*=-1; write(x); putchar('\n'); }
inline void writel(int x){ if (x<0) putchar('-'),x*=-1; write(x); putchar(' '); }
signed main () {
//    cerr<<(sizeof ls*3)<<endl;
    read(n); read(q);
    for (int i=1;i<=n;i++) 
      read(x),
      add(rt[i-1],rt[i],1,1000,x); 
    for (int i=1;i<=q;i++) {
        scanf("%s",ch);
        if (ch[0]=='M') {
            read(l[++tot]); read(r[tot]); read(w[tot]); 
        }
        else {
            ans=0;
            read(L); read(R); read(C);
            mp[L-1]=C; mp[R]=-C;
            for (int j=1;j<=tot;j++) {
                if (r[j]<L||l[j]>R) continue;
                    mp[Max(L,l[j])-1]-=w[j];
                    mp[Min(R,r[j])]+=w[j];
            }
            sum=0;
            for (it=mp.begin(),la=mp.begin();it!=mp.end();it++) {
                if (it!=mp.begin()) {
                    if (sum>1000) {la++; continue;}
                    ans+=que(rt[it->fi],1,1000,Max(sum,1));
                    ans-=que(rt[la->fi],1,1000,Max(sum,1)); la++;
                }
                sum+=it->se;
            } 
            mp.clear();printf("%d\n",ans);
        }
    }
}

 

posted @ 2018-09-04 20:54  泪寒之雪  阅读(139)  评论(0编辑  收藏  举报