sylvia 是一个热爱学习的女孩子,今天她想要学习数据结构技巧。
在看了一些博客学了一些姿势后,她想要找一些数据结构题来练练手。于是她的好朋友九条可怜酱给她出了一道题。
给出一个长度为 n 的数列 A,接下来有 m 次操作,操作有三种:
- 对于所有的 i∈[l,r],将 Ai 变成 Ai+x。
- 对于所有的 i∈[l,r],将 Ai 变成 ⌊Ai−−√⌋。
- 对于所有的 i∈[l,r],询问 Ai 的和。
作为一个不怎么熟练的初学者,sylvia 想了好久都没做出来。而可怜酱又外出旅游去了,一时间联系不上。于是她决定向你寻求帮助:你能帮她解决这个问题吗。
输入格式
第一行两个数:n,m。
接下来一行 n 个数 Ai。
接下来 m 行中,第 i 行第一个数 ti 表示操作类型:
若 ti=1,则接下来三个整数 li,ri,xi,表示操作一。
若 ti=2,则接下来三个整数 li,ri,表示操作二。
若 ti=3,则接下来三个整数 li,ri,表示操作三。
输出格式
对于每个询问操作,输出一行表示答案。
样例一
input
5 5 1 2 3 4 5 1 3 5 2 2 1 4 3 2 4 2 3 5 3 1 5
output
5 6
样例二
见样例数据下载。
限制与约定
测试点编号 | n 的规模 | m 的规模 | 其他约定 |
---|---|---|---|
1 | n≤3000 | m≤3000 | |
2 | |||
3 | |||
4 | n≤100000 | m≤100000 | 数据随机生成 |
5 | |||
6 | ti≠1 | ||
7 | |||
8 | |||
9 | |||
10 |
对于所有数据,保证有 1≤li≤ri≤n,1≤Ai,xi≤105
时间限制:1s
空间限制:256MB
上周做wannafly每日题目时碰上的题目,当天做的时候莫名WA,检查半天没发现问题就暂时先放下了,转眼间忙碌几天,直到周末才有时间再看一下。
从头读起,发现问题出在自己在add函数之前还擅自改了lazy数组的值,于是每次其实改的都是2次……
改完之后还是只有30分,另70分大数据错误出在runtimeerror,在此之前做线段树的题目一直都是把数组开到4倍,从来没出过问题,而这次re的原因就出在了这里。将4倍改成8倍之后就顺利AC。
头一次上uoj做题,翻翻其他的题目,发现很多都是高中信息竞赛的题目,集训队互测题目来源还看到了高中学长的名字……
看着这些oi的名称,真的是有一种又回到那样青葱的高中时光的感觉。虽然自己当初没学信息竞赛,数竞的结局也充满着无尽的遗憾,但如果不考虑结果,单纯地回想过去那段时光,真的,还是无比的开心与快乐啊。
大学,也会是像高中时光那样不经意就过去的呀,珍惜,这一次,一定不要再留遗憾。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cmath> 4 using namespace std; 5 typedef long long ll; 6 const int MAX=1e5+5; 7 ll big[MAX<<3],lit[MAX<<3],sum[MAX<<3],lazy[MAX<<3]; 8 int n,m; 9 ll an; 10 void pushup(int k) 11 { 12 big[k]=max(big[2*k],big[2*k+1]); 13 lit[k]=min(lit[2*k],lit[2*k+1]); 14 sum[k]=sum[2*k]+sum[2*k+1]; 15 } 16 void pushdown(int k,int l,int r) 17 { 18 if(lazy[k]!=0) 19 { 20 int mid=l+r>>1; 21 big[2*k]+=lazy[k];lit[2*k]+=lazy[k];sum[2*k]+=(ll)(mid-l+1)*lazy[k];lazy[2*k]+=lazy[k]; 22 big[2*k+1]+=lazy[k];lit[2*k+1]+=lazy[k];sum[2*k+1]+=(ll)(r-mid)*lazy[k];lazy[2*k+1]+=lazy[k]; 23 lazy[k]=0; 24 } 25 } 26 void init(int l,int r,int k) 27 { 28 lazy[k]=0; 29 if(l==r) 30 { 31 scanf("%lld",&big[k]); 32 lit[k]=sum[k]=big[k]; 33 return; 34 } 35 int mid=l+r>>1; 36 init(l,mid,2*k); 37 init(mid+1,r,2*k+1); 38 pushup(k); 39 } 40 void add(int al,int ar,int l,int r,int k,ll num) 41 { 42 if(l>=al&&r<=ar) 43 { 44 big[k]+=num;lit[k]+=num;sum[k]+=(ll)(r-l+1)*num; 45 lazy[k]+=num; 46 return; 47 } 48 pushdown(k,l,r); 49 int mid=l+r>>1; 50 if(al<=mid) 51 add(al,ar,l,mid,2*k,num); 52 if(ar>mid) 53 add(al,ar,mid+1,r,2*k+1,num); 54 pushup(k); 55 } 56 void div(int dl,int dr,int l,int r,int k) 57 { 58 pushdown(k,l,r); 59 ll tem,tem2; 60 if(l>=dl&&r<=dr) 61 { 62 if(lit[k]==big[k]) 63 { 64 tem=sqrt(lit[k]); 65 add(l,r,l,r,k,tem-big[k]); 66 return; 67 } 68 else if(lit[k]+1==big[k]) 69 { 70 tem=sqrt(lit[k]); 71 tem2=sqrt(big[k]); 72 if(tem+1==tem2) 73 { 74 add(l,r,l,r,k,tem2-big[k]); 75 return; 76 } 77 } 78 } 79 int mid=l+r>>1; 80 if(dl<=mid) 81 div(dl,dr,l,mid,2*k); 82 if(dr>mid) 83 div(dl,dr,mid+1,r,2*k+1); 84 pushup(k); 85 } 86 void query(int ql,int qr,int l,int r,int k) 87 { 88 pushdown(k,l,r); 89 if(l>=ql&&r<=qr) 90 { 91 an+=sum[k]; 92 return; 93 } 94 int mid=l+r>>1; 95 if(ql<=mid) 96 query(ql,qr,l,mid,2*k); 97 if(qr>mid) 98 query(ql,qr,mid+1,r,2*k+1); 99 pushup(k); 100 } 101 int main() 102 { 103 // freopen("ex_data2.in","r",stdin); 104 // freopen("myout.txt","w",stdout); 105 scanf("%d%d",&n,&m); 106 init(1,n,1); 107 int opt,l,r,x; 108 while(m--) 109 { 110 scanf("%d",&opt); 111 if(opt==1) 112 { 113 scanf("%d%d%d",&l,&r,&x); 114 add(l,r,1,n,1,x); 115 } 116 else if(opt==2) 117 { 118 scanf("%d%d",&l,&r); 119 div(l,r,1,n,1); 120 } 121 else 122 { 123 an=0; 124 scanf("%d%d",&l,&r); 125 query(l,r,1,n,1); 126 printf("%lld ",an); 127 } 128 } 129 return 0; 130 }