• bzoj 4695: 最假女选手 && Gorgeous Sequence HDU


    算导:

    核算法

    给每种操作一个摊还代价(是手工定义的),给数据结构中某些东西一个“信用”值(不是手动定义的,是被动产生的),摊还代价等于实际代价+信用变化量。

    当实际代价小于摊还代价时,增加等于差额的信用;

    当实际代价大于摊还代价时,减少等于差额的信用。

    显然总摊还代价等于总实际代价+总信用变化量。

    如果信用变化量始终>=0,那么总摊还代价给出总实际代价的一个上界;设法证明信用变化量始终>=0

    势能法

    对整个数据结构定义一个“势”函数$Phi$

    定义一个操作的摊还代价为实际代价加上势的变化量

    那么摊还代价的总和,等于实际代价的总和,加上整个过程中势的变化量

    如果“整个过程中势的变化量”始终大于等于0,那么摊还代价的总和,给出了实际代价总和的一个上界

    在实际代价难以计算的情况下,可以设计合适的势函数,使得每一次操作的摊还代价容易计算

    (其实就是把“信用”的定义换到整个数据结构上来)


    吉司机线段树:

    https://codeforces.com/blog/entry/57319

    实际上也不是就一定要用上面的方法..

    里面好像是先分析对势函数的修改,得到势函数增长的上限,而对于extranode,访问一个节点就会减少1的势函数,势函数又始终>=0,因此得到extranode访问次数的上限;其余的访问次数的证明套用普通线段树区间操作即可


    https://www.lydsy.com/JudgeOnline/problem.php?id=4695

    每个节点维护区间最小值,次小值,最小值出现次数,最大值,次大值,最大值出现次数,区间和

    (维护最小/大值出现次数,是为了方便在打上取min/取max标记同时,计算出对区间和的修改)

    维护取min标记,取max标记,加法标记(加法标记优先级最低,前面两个要手动定义一个优先级)

    然后用那篇cf帖子里面的方法做区间取min和区间取max操作,用普通线段树的方法做区间加法操作

    pushdown的时候按照手工定义的三个操作的优先级进行

    给节点加上标记时,细节很多,注意几个:

    先考虑对数值的影响,再考虑对之前标记的影响

    对数值的影响:

    加法操作:就是最(次)大(小)值都要加上这个数,也要对应修改区间和;

    取min/max操作:如果区间只有一种值或两种值,显然需要特判(就是打取min标记也要修改最小/次小值,打取max标记也要修改最大/次大值);打取min标记肯定要修改最大/次大值,打取max标记肯定要修改最小/次小值,肯定要对应修改区间和(具体方法:充分发扬人类智慧???就是说乱搞一下,能搞的)

    对之前标记的影响:举例:设优先级:取min标记>取max标记>加法标记

    要打取min/max标记了(设与x取min/max),如果之前有过加法标记(设加y),为了按照这个优先级的顺序做操作能得出正确结果,实际应该打上的标记是x-y;如果之前有过同样类型的标记,显然要对应取一下min/max

    要打取min标记了(与x取min),如果之前有过取max标记(与y取max),且x<y,那么数就是先变到(y)再变到小(x),要让这个取max标记也变为x

    pushup的细节也很多。。

    upd:以下所有代码tag_condition都要变成(l==r)||(原内容),pushdown都要加一句if(l==r)return;虽然因为某些原因没有出锅,但是最好还是加上以防万一(其实是另一个题出了锅)

      1 #pragma GCC optimize(3)
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<cstring>
      5 #include<vector>
      6 using namespace std;
      7 #define fi first
      8 #define se second
      9 #define mp make_pair
     10 #define pb push_back
     11 typedef long long ll;
     12 typedef unsigned long long ull;
     13 typedef pair<int,int> pii;
     14 int a[500100];
     15 namespace S
     16 {
     17 const int mininf=-0x7fffffff;
     18 const int maxinf=0x7fffffff;
     19 #define N 1050000
     20 #define lc (num<<1)
     21 #define rc (num<<1|1)
     22 struct I
     23 {
     24     int min1,min2,min1cnt;
     25     int max1,max2,max1cnt;
     26     ll sum;
     27 };
     28 I operator+(const I &a,const I &b)
     29 {
     30     I ans;ans.sum=a.sum+b.sum;
     31     if(a.min1<b.min1)
     32     {
     33         ans.min1=a.min1;ans.min1cnt=a.min1cnt;
     34         ans.min2=min(a.min2,b.min1);
     35     }
     36     else if(a.min1>b.min1)
     37     {
     38         ans.min1=b.min1;ans.min1cnt=b.min1cnt;
     39         ans.min2=min(b.min2,a.min1);
     40     }
     41     else
     42     {
     43         ans.min1=a.min1;ans.min1cnt=a.min1cnt+b.min1cnt;
     44         ans.min2=min(a.min2,b.min2);
     45     }
     46     if(a.max1>b.max1)
     47     {
     48         ans.max1=a.max1;ans.max1cnt=a.max1cnt;
     49         ans.max2=max(a.max2,b.max1);
     50     }
     51     else if(a.max1<b.max1)
     52     {
     53         ans.max1=b.max1;ans.max1cnt=b.max1cnt;
     54         ans.max2=max(b.max2,a.max1);
     55     }
     56     else
     57     {
     58         ans.max1=a.max1;ans.max1cnt=a.max1cnt+b.max1cnt;
     59         ans.max2=max(a.max2,b.max2);
     60     }
     61     return ans;
     62 }
     63 I d[N];
     64 int minv[N],maxv[N],addv[N];
     65 bool setmin[N],setmax[N];
     66 //规定标记:先取min,再取max,再加
     67 void putMax(int x,int l,int r,int num)
     68 //要求min1<x<min2
     69 //先考虑对数值的影响,再考虑对标记的影响
     70 {
     71     if(d[num].min1>=x)   return;
     72     //assert(x<d[num].min2);
     73     //if(setmax[num]&&x-addv[num]<maxv[num]) return;
     74     if(d[num].min2==maxinf) d[num].max1=x;
     75     else if(d[num].min1==d[num].max2)   d[num].max2=x;
     76     d[num].sum+=ll(d[num].min1cnt)*(x-d[num].min1);
     77     d[num].min1=x;
     78     if(!setmax[num])    setmax[num]=1,maxv[num]=x-addv[num];
     79     else maxv[num]=max(maxv[num],x-addv[num]);
     80 }
     81 void putMin(int x,int l,int r,int num)
     82 {
     83     if(d[num].max1<=x)   return;
     84     //assert(x>d[num].max2);
     85     //if(setmin[num]&&x-addv[num]>minv[num]) return;
     86     if(d[num].max2==mininf) d[num].min1=x;
     87     else if(d[num].max1==d[num].min2)   d[num].min2=x;
     88     d[num].sum-=ll(d[num].max1cnt)*(d[num].max1-x);
     89     d[num].max1=x;
     90     /*
     91     if(d[num].max2==mininf)
     92     {
     93         if(setmax[num])
     94         {
     95             if(maxv[num]>x)
     96             {
     97                 d[num].min1=x;
     98                 setmax[num]=0;
     99             }
    100         }
    101         else
    102             d[num].min1=x;
    103     }
    104     else if(d[num].max1==d[num].min2)
    105     {
    106         if(setmax[num])
    107         {
    108             if(maxv[num]<x)  d[num].min2=x;
    109             else
    110             {
    111                 d[num].min1=d[num].max1=x;
    112                 d[num].min2=maxinf;d[num].max2=mininf;
    113                 d[num].min1cnt=d[num].max1cnt=r-l+1;
    114                 setmax[num]=0;
    115             }
    116         }
    117         else
    118             d[num].min2=x;
    119     }
    120     */
    121     if(setmax[num]&&maxv[num]>x-addv[num])   maxv[num]=x-addv[num];
    122     if(!setmin[num])    setmin[num]=1,minv[num]=x-addv[num];
    123     else minv[num]=min(minv[num],x-addv[num]);
    124 }
    125 void doAdd(int x,int l,int r,int num)
    126 {
    127     d[num].sum+=ll(x)*(r-l+1);
    128     d[num].min1+=x;d[num].max1+=x;
    129     if(d[num].min2!=maxinf) d[num].min2+=x;
    130     if(d[num].max2!=mininf) d[num].max2+=x;
    131     addv[num]+=x;
    132 }
    133 void pd(int l,int r,int num)
    134 {
    135     int mid=l+((r-l)>>1);
    136     if(setmin[num])
    137     {
    138         putMin(minv[num],l,mid,lc);
    139         putMin(minv[num],mid+1,r,rc);
    140         setmin[num]=0;
    141     }
    142     if(setmax[num])
    143     {
    144         putMax(maxv[num],l,mid,lc);
    145         putMax(maxv[num],mid+1,r,rc);
    146         setmax[num]=0;
    147     }
    148     if(addv[num])
    149     {
    150         doAdd(addv[num],l,mid,lc);
    151         doAdd(addv[num],mid+1,r,rc);
    152         addv[num]=0;
    153     }
    154 }
    155 void build(int l,int r,int num)
    156 {
    157     if(l==r)
    158     {
    159         d[num].max1=d[num].min1=d[num].sum=a[l];
    160         d[num].max2=mininf;d[num].min2=maxinf;
    161         d[num].max1cnt=d[num].min1cnt=1;
    162         return;
    163     }
    164     int mid=l+((r-l)>>1);
    165     build(l,mid,lc);build(mid+1,r,rc);
    166     d[num]=d[lc]+d[rc];
    167 }
    168 void cmin(int L,int R,int x,int l,int r,int num)
    169 {
    170     if((r<L||R<l)||(d[num].max1<=x))   return;
    171     if((L<=l&&r<=R)&&(d[num].max2<x&&x<d[num].max1))
    172     {
    173         putMin(x,l,r,num);
    174         return;
    175     }
    176     pd(l,r,num);
    177     int mid=l+((r-l)>>1);
    178     cmin(L,R,x,l,mid,lc);
    179     cmin(L,R,x,mid+1,r,rc);
    180     d[num]=d[lc]+d[rc];
    181 }
    182 void cmax(int L,int R,int x,int l,int r,int num)
    183 {
    184     if((r<L||R<l)||(d[num].min1>=x))   return;
    185     if((L<=l&&r<=R)&&(d[num].min2>x&&x>d[num].min1))
    186     {
    187         putMax(x,l,r,num);
    188         return;
    189     }
    190     pd(l,r,num);
    191     int mid=l+((r-l)>>1);
    192     cmax(L,R,x,l,mid,lc);
    193     cmax(L,R,x,mid+1,r,rc);
    194     d[num]=d[lc]+d[rc];
    195 }
    196 void cadd(int L,int R,int x,int l,int r,int num)
    197 {
    198     if((r<L||R<l))    return;
    199     if((L<=l&&r<=R))
    200     {
    201         doAdd(x,l,r,num);
    202         return;
    203     }
    204     pd(l,r,num);
    205     int mid=l+((r-l)>>1);
    206     cadd(L,R,x,l,mid,lc);
    207     cadd(L,R,x,mid+1,r,rc);
    208     d[num]=d[lc]+d[rc];
    209 }
    210 I gett(int L,int R,int l,int r,int num)
    211 {
    212     if(L<=l&&r<=R)    return d[num];
    213     pd(l,r,num);
    214     int mid=l+((r-l)>>1);
    215     if(L<=mid&&mid<R) return gett(L,R,l,mid,lc)+gett(L,R,mid+1,r,rc);
    216     else if(L<=mid)  return gett(L,R,l,mid,lc);
    217     else if(mid<R)   return gett(L,R,mid+1,r,rc);
    218     else exit(-1);
    219 }
    220 #undef lc
    221 #undef rc
    222 }
    223 int n,m;
    224 int main()
    225 {
    226     int i,idx,l,r,x;
    227     //freopen("/tmp/4695/10.in","r",stdin);
    228     //freopen("/tmp/4695/10.ans","w",stdout);
    229     scanf("%d",&n);
    230     for(i=1;i<=n;i++)    scanf("%d",&a[i]);
    231     S::build(1,n,1);
    232     scanf("%d",&m);
    233     for(i=1;i<=m;i++)
    234     {
    235         scanf("%d",&idx);
    236         switch(idx)
    237         {
    238         case 1:
    239             scanf("%d%d%d",&l,&r,&x);
    240             S::cadd(l,r,x,1,n,1);
    241             break;
    242         case 2:
    243             scanf("%d%d%d",&l,&r,&x);
    244             S::cmax(l,r,x,1,n,1);
    245             break;
    246         case 3:
    247             scanf("%d%d%d",&l,&r,&x);
    248             S::cmin(l,r,x,1,n,1);
    249             break;
    250         case 4:
    251             scanf("%d%d",&l,&r);
    252             printf("%lld
    ",S::gett(l,r,1,n,1).sum);
    253             break;
    254         case 5:
    255             scanf("%d%d",&l,&r);
    256             printf("%d
    ",S::gett(l,r,1,n,1).max1);
    257             break;
    258         case 6:
    259             scanf("%d%d",&l,&r);
    260             printf("%d
    ",S::gett(l,r,1,n,1).min1);
    261             break;
    262         }
    263     }
    264     return 0;
    265 }
    View Code

    https://vjudge.net/problem/HDU-5306

      1 #pragma GCC optimize(3)
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<cstring>
      5 #include<vector>
      6 using namespace std;
      7 #define fi first
      8 #define se second
      9 #define mp make_pair
     10 #define pb push_back
     11 typedef long long ll;
     12 typedef unsigned long long ull;
     13 typedef pair<int,int> pii;
     14 int a[1000100];
     15 namespace S
     16 {
     17 const int mininf=-0x7fffffff;
     18 const int maxinf=0x7fffffff;
     19 #define N 2100000
     20 #define lc (num<<1)
     21 #define rc (num<<1|1)
     22 struct I
     23 {
     24     int min1,min2,min1cnt;
     25     int max1,max2,max1cnt;
     26     ll sum;
     27 };
     28 I operator+(const I &a,const I &b)
     29 {
     30     I ans;ans.sum=a.sum+b.sum;
     31     if(a.min1<b.min1)
     32     {
     33         ans.min1=a.min1;ans.min1cnt=a.min1cnt;
     34         ans.min2=min(a.min2,b.min1);
     35     }
     36     else if(a.min1>b.min1)
     37     {
     38         ans.min1=b.min1;ans.min1cnt=b.min1cnt;
     39         ans.min2=min(b.min2,a.min1);
     40     }
     41     else
     42     {
     43         ans.min1=a.min1;ans.min1cnt=a.min1cnt+b.min1cnt;
     44         ans.min2=min(a.min2,b.min2);
     45     }
     46     if(a.max1>b.max1)
     47     {
     48         ans.max1=a.max1;ans.max1cnt=a.max1cnt;
     49         ans.max2=max(a.max2,b.max1);
     50     }
     51     else if(a.max1<b.max1)
     52     {
     53         ans.max1=b.max1;ans.max1cnt=b.max1cnt;
     54         ans.max2=max(b.max2,a.max1);
     55     }
     56     else
     57     {
     58         ans.max1=a.max1;ans.max1cnt=a.max1cnt+b.max1cnt;
     59         ans.max2=max(a.max2,b.max2);
     60     }
     61     return ans;
     62 }
     63 I d[N];
     64 int minv[N],maxv[N],addv[N];
     65 bool setmin[N],setmax[N];
     66 //规定标记:先取min,再取max,再加
     67 void putMax(int x,int l,int r,int num)
     68 //要求min1<x<min2
     69 //先考虑对数值的影响,再考虑对标记的影响
     70 {
     71     if(d[num].min1>=x)    return;
     72     //assert(x<d[num].min2);
     73     //if(setmax[num]&&x-addv[num]<maxv[num])    return;
     74     if(d[num].min2==maxinf)    d[num].max1=x;
     75     else if(d[num].min1==d[num].max2)    d[num].max2=x;
     76     d[num].sum+=ll(d[num].min1cnt)*(x-d[num].min1);
     77     d[num].min1=x;
     78     if(!setmax[num])    setmax[num]=1,maxv[num]=x-addv[num];
     79     else maxv[num]=max(maxv[num],x-addv[num]);
     80 }
     81 void putMin(int x,int l,int r,int num)
     82 {
     83     if(d[num].max1<=x)    return;
     84     //assert(x>d[num].max2);
     85     //if(setmin[num]&&x-addv[num]>minv[num])    return;
     86     if(d[num].max2==mininf)    d[num].min1=x;
     87     else if(d[num].max1==d[num].min2)    d[num].min2=x;
     88     d[num].sum-=ll(d[num].max1cnt)*(d[num].max1-x);
     89     d[num].max1=x;
     90     /*
     91     if(d[num].max2==mininf)
     92     {
     93         if(setmax[num])
     94         {
     95             if(maxv[num]>x)
     96             {
     97                 d[num].min1=x;
     98                 setmax[num]=0;
     99             }
    100         }
    101         else
    102             d[num].min1=x;
    103     }
    104     else if(d[num].max1==d[num].min2)
    105     {
    106         if(setmax[num])
    107         {
    108             if(maxv[num]<x)    d[num].min2=x;
    109             else
    110             {
    111                 d[num].min1=d[num].max1=x;
    112                 d[num].min2=maxinf;d[num].max2=mininf;
    113                 d[num].min1cnt=d[num].max1cnt=r-l+1;
    114                 setmax[num]=0;
    115             }
    116         }
    117         else
    118             d[num].min2=x;
    119     }
    120     */
    121     if(setmax[num]&&maxv[num]>x-addv[num])    maxv[num]=x-addv[num];
    122     if(!setmin[num])    setmin[num]=1,minv[num]=x-addv[num];
    123     else minv[num]=min(minv[num],x-addv[num]);
    124 }
    125 void doAdd(int x,int l,int r,int num)
    126 {
    127     d[num].sum+=ll(x)*(r-l+1);
    128     d[num].min1+=x;d[num].max1+=x;
    129     if(d[num].min2!=maxinf)    d[num].min2+=x;
    130     if(d[num].max2!=mininf)    d[num].max2+=x;
    131     addv[num]+=x;
    132 }
    133 void pd(int l,int r,int num)
    134 {
    135     int mid=l+((r-l)>>1);
    136     if(setmin[num])
    137     {
    138         putMin(minv[num],l,mid,lc);
    139         putMin(minv[num],mid+1,r,rc);
    140         setmin[num]=0;
    141     }
    142     if(setmax[num])
    143     {
    144         putMax(maxv[num],l,mid,lc);
    145         putMax(maxv[num],mid+1,r,rc);
    146         setmax[num]=0;
    147     }
    148     if(addv[num])
    149     {
    150         doAdd(addv[num],l,mid,lc);
    151         doAdd(addv[num],mid+1,r,rc);
    152         addv[num]=0;
    153     }
    154 }
    155 void build(int l,int r,int num)
    156 {
    157     setmin[num]=setmax[num]=0;addv[num]=0;
    158     if(l==r)
    159     {
    160         d[num].max1=d[num].min1=d[num].sum=a[l];
    161         d[num].max2=mininf;d[num].min2=maxinf;
    162         d[num].max1cnt=d[num].min1cnt=1;
    163         return;
    164     }
    165     int mid=l+((r-l)>>1);
    166     build(l,mid,lc);build(mid+1,r,rc);
    167     d[num]=d[lc]+d[rc];
    168 }
    169 void cmin(int L,int R,int x,int l,int r,int num)
    170 {
    171     if((r<L||R<l)||(d[num].max1<=x))    return;
    172     if((L<=l&&r<=R)&&(d[num].max2<x&&x<d[num].max1))
    173     {
    174         putMin(x,l,r,num);
    175         return;
    176     }
    177     pd(l,r,num);
    178     int mid=l+((r-l)>>1);
    179     cmin(L,R,x,l,mid,lc);
    180     cmin(L,R,x,mid+1,r,rc);
    181     d[num]=d[lc]+d[rc];
    182 }
    183 void cmax(int L,int R,int x,int l,int r,int num)
    184 {
    185     if((r<L||R<l)||(d[num].min1>=x))    return;
    186     if((L<=l&&r<=R)&&(d[num].min2>x&&x>d[num].min1))
    187     {
    188         putMax(x,l,r,num);
    189         return;
    190     }
    191     pd(l,r,num);
    192     int mid=l+((r-l)>>1);
    193     cmax(L,R,x,l,mid,lc);
    194     cmax(L,R,x,mid+1,r,rc);
    195     d[num]=d[lc]+d[rc];
    196 }
    197 void cadd(int L,int R,int x,int l,int r,int num)
    198 {
    199     if((r<L||R<l))    return;
    200     if((L<=l&&r<=R))
    201     {
    202         doAdd(x,l,r,num);
    203         return;
    204     }
    205     pd(l,r,num);
    206     int mid=l+((r-l)>>1);
    207     cadd(L,R,x,l,mid,lc);
    208     cadd(L,R,x,mid+1,r,rc);
    209     d[num]=d[lc]+d[rc];
    210 }
    211 I gett(int L,int R,int l,int r,int num)
    212 {
    213     if(L<=l&&r<=R)    return d[num];
    214     pd(l,r,num);
    215     int mid=l+((r-l)>>1);
    216     if(L<=mid&&mid<R)    return gett(L,R,l,mid,lc)+gett(L,R,mid+1,r,rc);
    217     else if(L<=mid)    return gett(L,R,l,mid,lc);
    218     else if(mid<R)    return gett(L,R,mid+1,r,rc);
    219     else exit(-1);
    220 }
    221 #undef lc
    222 #undef rc
    223 }
    224 int n,m;
    225 int main()
    226 {
    227     int i,idx,l,r,x,T;
    228     scanf("%d",&T);
    229     while(T--){
    230     scanf("%d%d",&n,&m);
    231     for(i=1;i<=n;i++)    scanf("%d",&a[i]);
    232     S::build(1,n,1);
    233     for(i=1;i<=m;i++)
    234     {
    235         scanf("%d",&idx);
    236         switch(idx)
    237         {
    238         case 0:
    239             scanf("%d%d%d",&l,&r,&x);
    240             S::cmin(l,r,x,1,n,1);
    241             break;
    242         case 1:
    243             scanf("%d%d",&l,&r);
    244             printf("%d
    ",S::gett(l,r,1,n,1).max1);
    245             break;
    246         case 2:
    247             scanf("%d%d",&l,&r);
    248             printf("%lld
    ",S::gett(l,r,1,n,1).sum);
    249             break;
    250         }
    251     }}
    252     return 0;
    253 }
    View Code

    小B的序列

    http://210.33.19.103/contest/888/problem/2

    啧,貌似是原题https://www.lydsy.com/JudgeOnline/problem.php?id=5312

     

    题意:区间取and,区间取or,区间最大值

    对每一(二进制)位搞一个以上类型的线段树,那么修改操作相当于,对于某些位的线段树,区间对0取min或对1取max(对x取and就是x中为0的位对应线段树区间对0取min,对x取or就是x中为1的位对应线段树区间对1取max)

    当然这样子直接搞不能维护最大值,可以把所有位绑在一起,只建一个线段树,就可以维护了

    这样的话,当当前节点区间[l,r]被目标区间[L,R]完全包含时,如果存在一些操作位在这个区间有0也有1,那么必须要向下dfs;如果所有操作位在这个区间要么全0要么全1,那么就是说要么满足break_condition,要么满足tag_condition,但是这个不用细分,直接puttag就行了(可以发现效果不变的)

    错误记录:81,97行没有搞清问题本质,强行区分break和tag,于是复杂度错掉,T飞

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<vector>
      5 #include<cassert>
      6 using namespace std;
      7 #define fi first
      8 #define se second
      9 #define mp make_pair
     10 #define pb push_back
     11 typedef long long ll;
     12 typedef unsigned long long ull;
     13 typedef pair<int,int> pii;
     14 int a[200100];
     15 //int num1;
     16 namespace S
     17 {
     18 const int N=530000;
     19 const int all1=(1<<20)-1;
     20 #define lc (num<<1)
     21 #define rc (num<<1|1)
     22 //#define flip(x) (all1&(~(x)))
     23 #define flip(x) (all1^(x))
     24 int andv[N],orv[N],isall0[N],isall1[N],maxn[N];
     25 //先and,再or
     26 void doOr(int x,int l,int r,int num)
     27 {
     28     //if((isall1[num]&x)==x)    return;
     29     maxn[num]|=x;
     30     isall0[num]&=flip(x);isall1[num]|=x;
     31     orv[num]|=x;
     32 }
     33 void doAnd(int x,int l,int r,int num)
     34 {
     35     //if((isall0[num]&flip(x))==flip(x))    return;
     36     maxn[num]&=x;
     37     isall1[num]&=x;isall0[num]|=flip(x);
     38     andv[num]&=x;orv[num]&=x;
     39 }
     40 void pd(int l,int r,int num)
     41 {
     42     if(l==r)    return;
     43     int mid=l+((r-l)>>1);
     44     if(andv[num]!=all1)
     45     {
     46         doAnd(andv[num],l,mid,lc);
     47         doAnd(andv[num],mid+1,r,rc);
     48         andv[num]=all1;
     49     }
     50     if(orv[num])
     51     {
     52         doOr(orv[num],l,mid,lc);
     53         doOr(orv[num],mid+1,r,rc);
     54         orv[num]=0;
     55     }
     56 }
     57 void upd(int l,int r,int num)
     58 {
     59     isall0[num]=isall0[lc]&isall0[rc];
     60     isall1[num]=isall1[lc]&isall1[rc];
     61     maxn[num]=max(maxn[lc],maxn[rc]);
     62 }
     63 void build(int l,int r,int num)
     64 {
     65     andv[num]=all1;orv[num]=0;
     66     if(l==r)
     67     {
     68         isall0[num]=flip(a[l]);
     69         isall1[num]=a[l];
     70         maxn[num]=a[l];
     71         return;
     72     }
     73     int mid=l+((r-l)>>1);
     74     build(l,mid,lc);build(mid+1,r,rc);
     75     upd(l,r,num);
     76 }
     77 void cor(int L,int R,int x,int l,int r,int num)
     78 {//num1++;
     79     if((r<L||R<l))    return;
     80     //printf("or%d %d %d
    ",l,r,num);
     81     if(l==r||((L<=l&&r<=R)&&(((isall0[num]&x)|(isall1[num]&x))==x)))
     82     {
     83         doOr(x,l,r,num);
     84         return;
     85     }
     86     //if(l==r)  return;
     87     pd(l,r,num);
     88     int mid=l+((r-l)>>1);
     89     cor(L,R,x,l,mid,lc);
     90     cor(L,R,x,mid+1,r,rc);
     91     upd(l,r,num);
     92 }
     93 void cand(int L,int R,int x,int l,int r,int num)
     94 {//num1++;
     95     if((r<L||R<l))    return;
     96     //printf("and%d %d %d
    ",l,r,num);
     97     if(l==r||((L<=l&&r<=R)&&(((isall1[num]&flip(x))|(isall0[num]&flip(x)))==flip(x))))
     98     {
     99         doAnd(x,l,r,num);
    100         return;
    101     }
    102     //if(l==r)  return;
    103     pd(l,r,num);
    104     int mid=l+((r-l)>>1);
    105     cand(L,R,x,l,mid,lc);
    106     cand(L,R,x,mid+1,r,rc);
    107     upd(l,r,num);
    108 }
    109 int gmax(int L,int R,int l,int r,int num)
    110 {
    111     if(L<=l&&r<=R)    return maxn[num];
    112     pd(l,r,num);
    113     int mid=l+((r-l)>>1),ans=-1;
    114     if(L<=mid)   ans=max(ans,gmax(L,R,l,mid,lc));
    115     if(mid<R)    ans=max(ans,gmax(L,R,mid+1,r,rc));
    116     return ans;
    117 }
    118 #undef lc
    119 #undef rc
    120 }
    121 int n,q;
    122 int main()
    123 {
    124     int i,idx,l,r,x;
    125     scanf("%d%d",&n,&q);
    126     for(i=1;i<=n;i++)    scanf("%d",&a[i]);
    127     S::build(1,n,1);
    128     while(q--)
    129     {
    130         //int t=num1;
    131         scanf("%d",&idx);
    132         switch(idx)
    133         {
    134         case 1:
    135             scanf("%d%d%d",&l,&r,&x);
    136             S::cand(l,r,x,1,n,1);
    137             break;
    138         case 2:
    139             scanf("%d%d%d",&l,&r,&x);
    140             S::cor(l,r,x,1,n,1);
    141             break;
    142         case 3:
    143             scanf("%d%d",&l,&r);
    144             S::gmax(l,r,1,n,1);
    145             printf("%d
    ",S::gmax(l,r,1,n,1));
    146         }
    147         //if(num1-t>100000)  printf("%d
    ",num1-t);
    148         //if(q%1000==0)printf("test%d
    ",num1);
    149     }
    150     return 0;
    151 }
    View Code

    https://www.lydsy.com/JudgeOnline/problem.php?id=4355

    接着改板子。。。

    错误记录:17行最大值不够大

      1 #pragma GCC optimize(3)
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<cstring>
      5 #include<vector>
      6 using namespace std;
      7 #define fi first
      8 #define se second
      9 #define mp make_pair
     10 #define pb push_back
     11 typedef long long ll;
     12 typedef unsigned long long ull;
     13 typedef pair<int,int> pii;
     14 ll a[500100];
     15 namespace S
     16 {
     17 const ll maxinf=0x7fffffffffffffff;
     18 #define N 1050000
     19 #define lc (num<<1)
     20 #define rc (num<<1|1)
     21 struct I
     22 {
     23     ll min1,min2,min1cnt;
     24 };
     25 I operator+(const I &a,const I &b)
     26 {
     27     I ans;
     28     if(a.min1<b.min1)
     29     {
     30         ans.min1=a.min1;ans.min1cnt=a.min1cnt;
     31         ans.min2=min(a.min2,b.min1);
     32     }
     33     else if(a.min1>b.min1)
     34     {
     35         ans.min1=b.min1;ans.min1cnt=b.min1cnt;
     36         ans.min2=min(b.min2,a.min1);
     37     }
     38     else
     39     {
     40         ans.min1=a.min1;ans.min1cnt=a.min1cnt+b.min1cnt;
     41         ans.min2=min(a.min2,b.min2);
     42     }
     43     return ans;
     44 }
     45 I d[N];
     46 ll maxv[N],addv[N],setv[N];
     47 bool setmax[N],set[N];
     48 //规定标记:先赋值,再取max,再加
     49 void putMax(ll x,int l,int r,int num)
     50 //要求min1<x<min2
     51 //先考虑对数值的影响,再考虑对标记的影响
     52 {
     53     if(d[num].min1>=x)   return;
     54     d[num].min1=x;
     55     if(!setmax[num])    setmax[num]=1,maxv[num]=x-addv[num];
     56     else maxv[num]=max(maxv[num],x-addv[num]);
     57 }
     58 void doSet(ll x,int l,int r,int num)
     59 {
     60     d[num].min1=x;d[num].min2=maxinf;d[num].min1cnt=r-l+1;
     61     setmax[num]=0;addv[num]=0;
     62     set[num]=1;setv[num]=x;
     63 }
     64 void doAdd(ll x,int l,int r,int num)
     65 {
     66     d[num].min1+=x;
     67     if(d[num].min2!=maxinf) d[num].min2+=x;
     68     addv[num]+=x;
     69 }
     70 void pd(int l,int r,int num)
     71 {
     72     int mid=l+((r-l)>>1);
     73     if(set[num])
     74     {
     75         doSet(setv[num],l,mid,lc);
     76         doSet(setv[num],mid+1,r,rc);
     77         set[num]=0;
     78     }
     79     if(setmax[num])
     80     {
     81         putMax(maxv[num],l,mid,lc);
     82         putMax(maxv[num],mid+1,r,rc);
     83         setmax[num]=0;
     84     }
     85     if(addv[num])
     86     {
     87         doAdd(addv[num],l,mid,lc);
     88         doAdd(addv[num],mid+1,r,rc);
     89         addv[num]=0;
     90     }
     91 }
     92 void build(int l,int r,int num)
     93 {
     94     if(l==r)
     95     {
     96         d[num].min1=a[l];
     97         d[num].min2=maxinf;
     98         d[num].min1cnt=1;
     99         return;
    100     }
    101     int mid=l+((r-l)>>1);
    102     build(l,mid,lc);build(mid+1,r,rc);
    103     d[num]=d[lc]+d[rc];
    104 }
    105 void cmax(int L,int R,ll x,int l,int r,int num)
    106 {
    107     if((r<L||R<l)||(d[num].min1>=x))   return;
    108     if((L<=l&&r<=R)&&(d[num].min2>x&&x>d[num].min1))
    109     {
    110         putMax(x,l,r,num);
    111         return;
    112     }
    113     pd(l,r,num);
    114     int mid=l+((r-l)>>1);
    115     cmax(L,R,x,l,mid,lc);
    116     cmax(L,R,x,mid+1,r,rc);
    117     d[num]=d[lc]+d[rc];
    118 }
    119 void cadd(int L,int R,ll x,int l,int r,int num)
    120 {
    121     if((r<L||R<l))    return;
    122     if((L<=l&&r<=R))
    123     {
    124         doAdd(x,l,r,num);
    125         return;
    126     }
    127     pd(l,r,num);
    128     int mid=l+((r-l)>>1);
    129     cadd(L,R,x,l,mid,lc);
    130     cadd(L,R,x,mid+1,r,rc);
    131     d[num]=d[lc]+d[rc];
    132 }
    133 void cset(int L,int R,ll x,int l,int r,int num)
    134 {
    135     if((r<L||R<l))    return;
    136     if((L<=l&&r<=R))
    137     {
    138         doSet(x,l,r,num);
    139         return;
    140     }
    141     pd(l,r,num);
    142     int mid=l+((r-l)>>1);
    143     cset(L,R,x,l,mid,lc);
    144     cset(L,R,x,mid+1,r,rc);
    145     d[num]=d[lc]+d[rc];
    146 }
    147 I gett(int L,int R,int l,int r,int num)
    148 {
    149     if(L<=l&&r<=R)    return d[num];
    150     pd(l,r,num);
    151     int mid=l+((r-l)>>1);
    152     if(L<=mid&&mid<R) return gett(L,R,l,mid,lc)+gett(L,R,mid+1,r,rc);
    153     else if(L<=mid)  return gett(L,R,l,mid,lc);
    154     else if(mid<R)   return gett(L,R,mid+1,r,rc);
    155     else exit(-1);
    156 }
    157 #undef lc
    158 #undef rc
    159 }
    160 int n,m;
    161 int main()
    162 {
    163     int i,idx,l,r;ll x;S::I ttt;
    164     //freopen("/tmp/4355/11.in","r",stdin);
    165     //freopen("/tmp/4355/11.ans","w",stdout);
    166     scanf("%d%d",&n,&m);
    167     for(i=1;i<=n;i++)    scanf("%lld",&a[i]);
    168     S::build(1,n,1);
    169     for(i=1;i<=m;i++)
    170     {
    171         scanf("%d",&idx);
    172         switch(idx)
    173         {
    174         case 1:
    175             scanf("%d%d%lld",&l,&r,&x);
    176             S::cset(l,r,x,1,n,1);
    177             break;
    178         case 2:
    179             scanf("%d%d%lld",&l,&r,&x);
    180             S::cadd(l,r,x,1,n,1);
    181             S::cmax(l,r,0,1,n,1);
    182             break;
    183         case 3:
    184             scanf("%d%d",&l,&r);
    185             ttt=S::gett(l,r,1,n,1);
    186             printf("%lld
    ",ttt.min1==0?ttt.min1cnt:0);
    187         }
    188     }
    189     return 0;
    190 }
    View Code
  • 相关阅读:
    C# 还原SQL数据库(非存储过程方式)
    C# 无边框窗体移动代码
    SQL 2008 R2 数据库镜像操作
    序列号
    Oracle VM VirtualBox 随系统自动启动虚拟机的方法
    SQL每个用户最后的一条记录
    JS判断是否在微信浏览器打开
    使用device.js检测设备并实现不同设备展示不同网页
    check单选框多个全选与取消全选
    判断滚动是否到达底部
  • 原文地址:https://www.cnblogs.com/hehe54321/p/9403652.html
Copyright © 2020-2023  润新知