积木---------------权值线段树,模拟
问题描述
Alien 喜欢玩积木,场地是一横排底座,一开始都没有积木,编号为 1~10^6 。
若对于任意 l<=k<=r,第k 列上存在积木,且第 l-1 列不存在积木或 l=1,第
r+1 列不存在积木或 r=10^6 ,则称第 l~r 列为一个塔,
第 l 列为该塔的第 1 列,该塔的长度为 r-l+1。由于堆积木太累,他新买了一
个机器人帮他堆积木,机器人有两种操作:
put x c:表示在第 x 列上增加c 个积木(c>0)。
tput t x c:表示在塔 t 的第 x 列上增加c 个积木(c>0)。
由于机器人能搬运的积木太多,一排积木让他眼花缭乱,
你需要回答四种问题:
towers:询问共有几座塔。
cubes t:询问第 t 座塔共有几个积木。
length t:询问第 t 座塔的长度。
tcubes t x:询问第 t 座塔的第 x 列有几个积木。
现给出机器人的所有操作,请回答所有询问。
数据保证每一列的积木数不超过 int 范围。
输入
第一行为总操作和询问的数量 n。下面 n 行表示机器人的操作和 Alien 的询问。【输出】对于每个询问输出一行,具体格式见样例。
输入样例
22
towers
put 2 5
put 1 6
put 3 6
put 3 3
towers
length 1
put 6 3
put 5 4
length 2
tcubes 2 1
tcubes 2 2
towers
cubes 1
cubes 2
put 4 3
towers
cubes 1
tput 1 6 50
cubes 1
tcubes 1 6
length 1
输出样例
0 towers
1 towers
length of 1th tower is 3
length of 2th tower is 2
4 cubes in 1th column of 2th tower
3 cubes in 2th column of 2th tower
2 towers
20 cubes in 1th tower
7 cubes in 2th tower
1 towers
30 cubes in 1th tower
80 cubes in 1th tower
53 cubes in 6th column of 1th tower
length of 1th tower is 6
数据说明
对于 10% 的数据 只含操作 put 和询问 tower,
对于另 20% 的数据 n<=10,
对于 100% 的数据 0<n<=10^6 ,保证数据合法。
1. 可以发现该题最主要的操作就是查询第 k 个 tower。
2. 上述操作用权值线段树维护即可。
3. 然后就是模拟了。
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 int n,z,x,pos; 5 char opt[10]; 6 ll s[1000050],y; 7 int len[1000050],fa[1000050]; 8 struct tree 9 { 10 int sum[4000050]; 11 void calc_add(int u,int v,int val,int l,int r) 12 { 13 sum[u]+=val; 14 if(l==r) 15 return ; 16 int mid=(l+r)>>1; 17 if(v<=mid) 18 calc_add(u<<1,v,val,l,mid); 19 else 20 calc_add(u<<1|1,v,val,mid+1,r); 21 } 22 int calc_ask(int u,int v,int l,int r) 23 { 24 if(l==r) 25 return l; 26 int mid=(l+r)>>1; 27 if(v<=sum[u<<1]) 28 return calc_ask(u<<1,v,l,mid); 29 else 30 return calc_ask(u<<1|1,v-sum[u<<1],mid+1,r); 31 } 32 }tow; 33 struct szsz 34 { 35 ll c[1000050]; 36 void calc_add(int u,ll v) 37 { 38 while(u<=1e6) 39 { 40 c[u]+=v; 41 u+=u&-u; 42 } 43 } 44 ll calc_ask(int u) 45 { 46 ll sum=0; 47 while(u) 48 { 49 sum+=c[u]; 50 u-=u&-u; 51 } 52 return sum; 53 } 54 }val; 55 int find(int u) 56 { 57 return fa[u]==u? u:fa[u]=find(fa[u]); 58 } 59 int main() 60 { 61 for(int i=1;i<=1e6;++i) 62 fa[i]=i; 63 scanf("%d",&n); 64 while(n--) 65 { 66 scanf(" %s",opt); 67 if(opt[0]=='p') 68 { 69 scanf("%d%lld",&x,&y); 70 s[x]+=y; 71 val.calc_add(x,y); 72 if(s[x]==y) 73 { 74 if(s[x-1]==0&&s[x+1]==0) 75 { 76 tow.calc_add(1,x,1,1,1e6); 77 len[x]=1; 78 } 79 else if(s[x-1]&&!s[x+1]) 80 { 81 ++len[find(x-1)]; 82 fa[x]=fa[x-1]; 83 } 84 else if(s[x+1]&&!s[x-1]) 85 { 86 len[x]=len[x+1]+1; 87 len[x+1]=0; 88 fa[x+1]=x; 89 tow.calc_add(1,x+1,-1,1,1e6); 90 tow.calc_add(1,x,1,1,1e6); 91 } 92 else 93 { 94 pos=find(x-1); 95 fa[x+1]=pos; 96 len[pos]+=len[x+1]+1; 97 len[x+1]=0; 98 tow.calc_add(1,x+1,-1,1,1e6); 99 } 100 } 101 } 102 else if(opt[1]=='p') 103 { 104 scanf("%d%d%lld",&z,&x,&y); 105 pos=tow.calc_ask(1,z,1,1e6)+x-1; 106 val.calc_add(pos,y); 107 s[pos]+=y; 108 } 109 else if(opt[1]=='o') 110 { 111 printf("%d towers\n",tow.sum[1]); 112 } 113 else if(opt[1]=='u') 114 { 115 scanf("%d",&z); 116 pos=tow.calc_ask(1,z,1,1e6); 117 printf("%lld cubes in %dth tower\n",val.calc_ask(pos+len[pos]-1)-val.calc_ask(pos-1),z); 118 } 119 else if(opt[1]=='e') 120 { 121 scanf("%d",&z); 122 pos=tow.calc_ask(1,z,1,1e6); 123 printf("length of %dth tower is %d\n",z,len[pos]); 124 } 125 else if(opt[1]=='c') 126 { 127 scanf("%d%d",&z,&x); 128 pos=tow.calc_ask(1,z,1,1e6); 129 printf("%lld cubes in %dth column of %dth tower\n",s[pos+x-1],x,z); 130 } 131 } 132 return 0; 133 }