题目:

【题目描述】

现有给定一个序列a_0,a_1,.....a_(n-1)共n项以及m个操作。操作分成以下三类:

0: 将区间[l,r]中的数加上一个值x

1: 将区间[l,r]中的数乘上-1

2: 询问区间[l,r]中的数的绝对值之和

编程实现以上操作。

【输入格式】

第一行两个数n,m,分别表示序列的长度和操作的个数

第二行n个数,第i个数表示a_(i-1)

第三至m+2行,每行采取下列形式之一:

0 l r x (表示第0种操作)

1 l r (表示第1种操作)

2 l r (表示第2种操作)

l,r,x意义如题目描述中所述。

【输出格式】

共k行(其中k是第2种操作的个数),第i行有且仅有一个数,表示第i次第2种操作的答案。

【样例输入】

4 4

-2 -1 0 1

2 0 3

1 1 3

0 0 1 2

2 0 2

【样例输出】

4

3

【时空限制与数据约束】

时间:3s  空间:256MB

对于40%的数据,n,m<=10000

对于100%的数据,n,m<=100000

数据保证所有时刻序列中的数的绝对值总和不会超过64位有符号整形范围。

题解:

  乍一看以为是水题……写了一个多小时Seg套Splay发现调不出来……oh,fxxk!然后就mengbier了= =。

  zyf大佬使用吉司机线段树思想?(这是什么?)

  题解是分块233,真是妙啊。

  当时一心想怎么用线段树维护233,没有考虑用分块/莫队……emmmm,真是

  改起来也十分不方便……真的很naive……

  考虑如何维护,因为*-1实际上绝对值不会改变只是每个值从$now[x]=a[x]+add[bel[x]]$改变为$-now[x]$,但以后给该元素+add就会变为-add,画个图就明白了,这样搞定了操作0。

  然后对于*-1的维护(当然是两边的啦),假设这个块被标记了奇数次-1,那么实际每个数值均为当前记录的值的相反数,但是我们又有一部分变为了偶数次-1,发现假设块的add不变,我们直接给这几个值*-1是错的,(列列式子就明白),那么处理这个问题有两种方式,1是块里每个元素+add再乘-1,然后把add清空,再把部分修改的值*-1,重建这个块,2是给修改元素+add*2,再*-1。第一个很好理解,第二个化化式子就明白了。

  当然由于维护块内答案需要二分,所以要把块设的小一点。

代码:

  1 #include "bits/stdc++.h"
  2 
  3 using namespace std;
  4 
  5 typedef long long ll;
  6 
  7 inline int read(){
  8     int s=0,k=1;char ch=getchar();
  9     while (ch<'0'|ch>'9')   ch=='-'?k=-1:0,ch=getchar();
 10     while (ch>47&ch<='9')   s=s*10+(ch^48),ch=getchar();
 11     return s*k;
 12 }
 13 
 14 
 15 inline ll readll(){
 16     ll s=0,k=1;char ch=getchar();
 17     while (ch<'0'|ch>'9')   ch=='-'?k=-1:0,ch=getchar();
 18     while (ch>47&ch<='9')   s=s*10+(ch^48),ch=getchar();
 19     return s*k;
 20 }
 21 
 22 const int N=1e5+10;
 23 
 24 
 25 ll a[N],ans[N],mo[N],b[1005][202],sum[1005][205];
 26 
 27 bool rev[N];
 28 
 29 int n,m,leth,bel[N],vis[N],L[N],R[N];
 30 
 31 inline void build(int op,int l,int r){
 32     int i;
 33     memcpy(b[op],a+l,sizeof b[op]);
 34     sort(b[op],b[op]+r-l+1);
 35     memcpy(sum[op],b[op],sizeof sum[op]);
 36     ans[op]=abs(b[op][0]+mo[op]);
 37     for (i=1;i+l<=r;++i)
 38         sum[op][i]+=sum[op][i-1],ans[op]+=abs(b[op][i]+mo[op]);
 39     vis[op]=0;
 40 }
 41 
 42 inline void update(int l,int r,int lk,int rk,ll add){        
 43     int i;
 44     if(lk==rk)  {
 45         if(rev[lk]) add=-add;
 46         for (i=l;i<=r;++i) a[i]+=add;
 47         build(lk,L[lk],R[lk]);
 48     }else   {
 49         ll pl;
 50         if(rev[lk]) pl=-add;else pl=add;
 51         for (i=l;i<=R[lk];++i)  a[i]+=pl;
 52         build(lk,L[lk],R[lk]);
 53         if(rev[rk]) pl=-add;else    pl=add;
 54         for (i=L[rk];i<=r;++i)  a[i]+=pl;
 55         build(rk,L[rk],R[rk]);
 56         for (i=lk+1;i<rk;++i)   mo[i]+=(rev[i]?-add:add),vis[i]=true;
 57     }
 58 }
 59 
 60 inline void sigh(int l,int r,int lk,int rk){        
 61     int i;
 62     if(lk==rk)  {
 63         for (i=l;i<=r;++i)   a[i]=-(a[i]+2*mo[lk]);
 64         build(lk,L[lk],R[lk]);
 65     }else   {
 66         for (i=l;i<=R[lk];++i)  a[i]=-(a[i]+2*mo[lk]);
 67         build(lk,L[lk],R[lk]);
 68         for (i=L[rk];i<=r;++i)  a[i]=-(a[i]+2*mo[rk]);
 69         build(rk,L[rk],R[rk]);
 70         for (i=lk+1;i<rk;++i)   rev[i]^=1;
 71     }
 72 } 
 73 
 74 inline ll query (int op){
 75     int l=-1,r=R[op]-L[op]+1,mid;
 76     while(l+1<r){
 77         int mid=l+r>>1;
 78         if(b[op][mid]+mo[op]>=0)   r=mid;
 79         else    l=mid;
 80     }
 81     vis[op]=0;
 82     ans[op]=(sum[op][R[op]-L[op]]-sum[op][l])+mo[op]*(R[op]-l-L[op])
 83             -((l+1)*mo[op]+sum[op][l]);   
 84     return ans[op];
 85 }
 86 
 87 inline ll query (int l,int r,int lk,int rk){
 88     ll ret=0;int i;
 89     if(lk==rk)  
 90         for (i=l;i<=r;++i)      ret+=abs(a[i]+mo[lk]);
 91     else   {
 92         for (i=l;i<=R[lk];++i)  ret+=abs(a[i]+mo[lk]);
 93         for (i=L[rk];i<=r;++i)  ret+=abs(a[i]+mo[rk]);
 94         for (i=lk+1;i<rk;++i)   
 95             if(!vis[i]) ret+=ans[i];
 96             else    ret+=query(i);
 97     }
 98     return ret;
 99 }
100 
101 int main(){
102     scanf("%d%d",&n,&m);leth=100;
103     for (int i=1;i<=n;++i){
104         a[i]=readll();
105         bel[i]=(i-1)/leth;
106         L[bel[i]]?0:L[bel[i]]=i;
107         R[bel[i]]=i;
108         b[bel[i]][i-bel[i]*leth-1]=a[i];
109     }
110     register int i,j;
111 
112     for (i=0;i<=bel[n];++i){
113         sort(b[i],b[i]+R[i]-L[i]+1);
114         memcpy(sum[i],b[i],sizeof (sum[i]));
115         ans[i]=abs(b[i][0]);
116         for (j=1;j+L[i]<=R[i];++j) sum[i][j]+=sum[i][j-1],ans[i]+=abs(b[i][j]);
117     }
118     ll x;
119     int type,l,r;
120     int tot=0;
121     while (m--){
122         type=read(),l=read()+1,r=read()+1;
123         if(!type)   
124             x=read(),     update(l,r,bel[l],bel[r],x);
125         else   if(type&1)     sigh(l,r,bel[l],bel[r]);
126         else printf("%lld\n",query(l,r,bel[l],bel[r]));
127     }
128 }
t1

相关文章: