zoukankan      html  css  js  c++  java
  • codeforce 896E

    原题链接

    题目大意:

     给你一个序列,要求维护两种操作:

      1,l,r,x:   在l到r这个区间将所有 值大于X的数减X

      2, l,r,x  在l到r这个区间统计值等于X的数的个数。

      N(序列长度<=10^5),max(a)(序列中的最大值<=10^5).

      一道神题。

       我们首先应该想到用数据结构优化,但是标记下传至底之前我们不好统计答案。

       我们选择分块。

       我们考虑如何对一整块进行1操作。

       我们不妨对每一个块都统计其有几个X(X从1至10^5),并把值相同的元素串起来(用并查集维护)。

       我们对1操作进行分析,我们发现每一次操作都会使极差减小,我们很难在严格的O(1)内维护1操作,那么我们可以通过摊还分析,让每次极差减小1的操作时间复杂度达到O(1)。

      我们分情况讨论,若极差>=2x,那么我们就让最小的X个加上X,打上-X的懒标记,这个时候极差减少了X。

      若极差<2X,我们让最大的那几个减X就好,这时候我们做了min(V,极差-x)次,极差小了min(V,极差-x)。

      那么,我们就做好了。要更新边块(两侧的块)时,我们暴力修改,暴力重构就好了。

    #pragma GCC optimize("-O3")
    #include<bits/stdc++.h>
    #define sight(c) ('0'<=c&&c<='9')
    #define SIZ 254
    #define OTK 407
    #define Re register
    #define N 100607
    #define fp puts
    #define l(x) (x*SIZ-SIZ+1)
    #define r(x) (x*SIZ)
    inline void read(int &x){
        static char c;
        for (c=getchar();!sight(c);c=getchar());
        for (x=0;sight(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('
    '); }
    using namespace std;
    struct RR{int num,root;}V[OTK][N];
    int pre[N],pos[N],a[N],ma[N],n,m,be[N],op,l,r,v,p,q,ans,lz[N];
    inline int fa(int x){
        while (x^pre[x]) x=pre[x]=pre[pre[x]];  return x;
    }
    inline void push(int x) {
        for (Re int i=l(x);i<=r(x);i++) 
         a[i]=pos[fa(i)],V[x][a[i]].root=V[x][a[i]].num=0,a[i]-=lz[x];
        for (int i=l(x);i<=r(x);i++) pre[i]=0; lz[x]=0;
    }
    inline void reb(int x){
        ma[x]=0;
        for (Re int i=l(x);i<=r(x);i++) {
            if (a[i]>ma[x]) ma[x]=a[i];
            V[x][a[i]].root?pre[i]=V[x][a[i]].root:
            (pos[i]=a[i],V[x][a[i]].root=i,pre[i]=i);
            V[x][a[i]].num++;
        }
    }
    RR *A,*B;
    void play(int x,int a,int b){
        A=&V[x][a]; B=&V[x][b];
        B->root?pre[A->root]=B->root:(B->root=A->root,pos[A->root]=b);
        B->num+=A->num,A->num=A->root=0;
    }
    inline void det(intx,int v){
    int &p=lz[x] ,&q=ma[x];
        if ((v<<1)<=q-p) {
            for (Re int i=p+1;i<=p+v;i++)
             if (V[x][i].root) play(x,i,i+v);
            p+=v;
        } else {
            for (Re int i=q;i>p+v;i--)
              if (V[x][i].root) play(x,i,i-v);
            q=min(q,p+v);
        }
    }
    int main () {
        read(n); read(m);
        for (Re int i=1;i<=n;i++) 
         read(a[i]),be[i]=(i-1)/SIZ+1;
        for (Re int i=1;i<=be[n];i++) reb(i);
        while (m--) {
            read(op); read(l); read(r); read(v);
            switch (op) {
                case 1: p=be[l]; q=be[r];
                  if (p^q) {
                        push(p); push(q);
                        for (Re int i=l;i<=r(p);i++) if (a[i]>v) a[i]-=v;
                        for (Re int i=l(q);i<=r;i++) if (a[i]>v) a[i]-=v;
                        for (Re int i=p+1;i<q;i++) 
                         det(i,v);
                        reb(p); reb(q);
                  } else {
                       push(p);
                       for (Re int i=l;i<=r;i++) if (a[i]>v) a[i]-=v;
                       reb(p);
                  }
                break;
                case 2: p=be[l]; q=be[r]; ans=0;
                  if (p^q) {
                      for (Re int i=l;i<=r(p);i++) if (pos[fa(i)]-lz[p]==v) ans++;
                      for (Re int i=l(q);i<=r;i++) if (pos[fa(i)]-lz[q]==v) ans++;
                      for (Re int i=p+1;i<q;i++)
                        if (v+lz[i]<N) ans+=V[i][v+lz[i]].num; 
                    }else 
                     for (Re int i=l;i<=r;i++) if (pos[fa(i)]-lz[p]==v) ans++;
                   writeln(ans);
                break;
            }
        }
    }

    update :在洛谷也发现了这题,又交了一发,T且M,出题人在洛谷上只开了1s,128M,实在是幽(sang)默(xin)至(bing)极(kuang)。吓的我赶紧吧int换成unsigned char。

    #pragma GCC optimize("-O3")
    #include<bits/stdc++.h>
    #define sight(c) ('0'<=c&&c<='9')
    #define SIZ 253
    #define OTK 407
    #define Re register
    #define N 100607
    #define fp puts
    #define l(x) (x*SIZ-SIZ+1)
    #define r(x) (x*SIZ)
    inline void read(int &x){
        static char c;
        for (c=getchar();!sight(c);c=getchar());
        for (x=0;sight(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('
    '); }
    using namespace std;
    struct RR{unsigned char num,root;}V[OTK][N];
    int pre[N],pos[N],a[N],ma[N],n,m,be[N],op,l,r,v,p,q,ans,lz[N];
    inline int fa(int x){
        while (x^pre[x]) x=pre[x]=pre[pre[x]];  return x;
    }
    inline void push(int x) {
        for (Re int i=l(x);i<=r(x);i++) 
         a[i]=pos[fa(i)],V[x][a[i]].root=V[x][a[i]].num=0,a[i]-=lz[x];
        for (int i=l(x);i<=r(x);i++) pre[i]=0; lz[x]=0;
    }
    inline void reb(int x){
        ma[x]=0;
        for (Re int i=l(x);i<=r(x);i++) {
            if (a[i]>ma[x]) ma[x]=a[i];
            V[x][a[i]].root?pre[i]=V[x][a[i]].root+l(x)-1:
            (pos[i]=a[i],V[x][a[i]].root=i-l(x)+1,pre[i]=i);
            V[x][a[i]].num++;
        }
    }
    RR *A,*B;
    void play(int x,int a,int b){
        A=&V[x][a]; B=&V[x][b];
        B->root?pre[A->root+l(x)-1]=B->root+l(x)-1:(B->root=A->root,pos[A->root+l(x)-1]=b);
        B->num+=A->num,A->num=A->root=0;
    }
    inline void det(int x,int v){
        int &p=lz[x] ,&q=ma[x];
        if ((v<<1)<=q-p) {
            for (Re int i=p+1;i<=p+v;i++)
             if (V[x][i].root) play(x,i,i+v);
            p+=v;
        } else {
            for (Re int i=q;i>p+v;i--)
              if (V[x][i].root) play(x,i,i-v);
            q=min(q,p+v);
        }
    }
    int main () {
        read(n); read(m);
        for (Re int i=1;i<=n;i++) 
         read(a[i]),be[i]=(i-1)/SIZ+1;
        for (Re int i=1;i<=be[n];i++) reb(i);
        while (m--) {
            read(op); read(l); read(r); read(v);
            switch (op) {
                case 1: p=be[l]; q=be[r];
                  if (p^q) {
                        push(p); push(q);
                        for (Re int i=l;i<=r(p);i++) if (a[i]>v) a[i]-=v;
                        for (Re int i=l(q);i<=r;i++) if (a[i]>v) a[i]-=v;
                        for (Re int i=p+1;i<q;i++) 
                         det(i,v);
                        reb(p); reb(q);
                  } else {
                       push(p);
                       for (Re int i=l;i<=r;i++) if (a[i]>v) a[i]-=v;
                       reb(p);
                  }
                break;
                case 2: p=be[l]; q=be[r]; ans=0;
                  if (p^q) {
                      for (Re int i=l;i<=r(p);i++) if (pos[fa(i)]-lz[p]==v) ans++;
                      for (Re int i=l(q);i<=r;i++) if (pos[fa(i)]-lz[q]==v) ans++;
                      for (Re int i=p+1;i<q;i++)
                        if (v+lz[i]<N) ans+=V[i][v+lz[i]].num; 
                    }else 
                     for (Re int i=l;i<=r;i++) if (pos[fa(i)]-lz[p]==v) ans++;
                   writeln(ans);
                break;
            }
        }
    }

      

      

  • 相关阅读:
    android 75 新闻列表页面
    android 74 下载文本
    android 73 下载图片
    android 72 确定取消对话框,单选对话框,多选对话框
    android 71 ArrayAdapter和SimpleAdapter
    android 70 使用ListView把数据显示至屏幕
    maven如何将本地jar安装到本地仓库
    Centos6.7搭建ISCSI存储服务器
    解决maven打包编译出现File encoding has not been set问题
    MySQL 解决 emoji表情 的方法,使用utf8mb4 字符集(4字节 UTF-8 Unicode 编码)
  • 原文地址:https://www.cnblogs.com/rrsb/p/8323560.html
Copyright © 2011-2022 走看看