题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=263
题意:一排位置,开始全为0.若一段区间[L,R]之间均大于0且L-1和R+1均为0,我们说[L,R]为一段。两种改变,四种询问。改变是:(1)将第x个位置增加y;(2)将第t段的第x个位置增加y。四种询问是:(1)段的个数;(2)第t段中的所有数之和;(3)第t段的区间长度;(4)第t段上第x个位置的数是多少。
思路:一开始用splay+并查集WA了半天。最后看别人的BIT+并查集,好犀利。。。
int root[N],num[N],c[N],sum[N],p[N];
int n;
int getRoot(int x)
{
if(root[x]!=x) root[x]=getRoot(root[x]);
return root[x];
}
int search(int c[],int x,int y)
{
int ans=0;
while(y) ans+=c[y],y-=y&-y;
x--;
while(x) ans-=c[x],x-=x&-x;
return ans;
}
void insert(int c[],int x,int det)
{
while(x<N) c[x]+=det,x+=x&-x;
}
void Union(int x,int y)
{
num[x]+=num[y];
root[y]=x;
}
int getStart(int k)
{
int low=1,high=N-1,mid,temp;
while(low<=high)
{
mid=(low+high)>>1;
if(search(c,1,mid)<k) low=mid+1;
else high=mid-1;
}
if(high>=1&&search(c,1,high)==k) return high;
return low;
}
void putCube(int x,int y)
{
insert(sum,y,x);
if(p[y]) return;
p[y]=1;
x=getRoot(y-1);
if(p[x]) Union(x,y);
else insert(c,y,1);
if(p[y+1])
{
insert(c,y+1,-1);
x=getRoot(y);
Union(x,y+1);
}
}
void put()
{
int x,c;
scanf("%d%d",&x,&c);
putCube(c,x);
}
void tput()
{
int t,x,c,p;
scanf("%d%d%d",&t,&x,&c);
p=getStart(t);
putCube(c,p+x-1);
}
void towers()
{
printf("%d towers\n",search(c,1,N-1));
}
void cubes()
{
int t,p;
scanf("%d",&t);
p=getStart(t);
printf("%d cubes in %dth tower\n", search(sum,p,p+num[p]-1),t);
}
void length()
{
int t,p;
scanf("%d",&t);
p=getStart(t);
printf("length of %dth tower is %d\n",t,num[p]);
}
void tcubes()
{
int t,x,p;
scanf("%d%d",&t,&x);
p=getStart(t)+x-1;
printf("%d cubes in %dth column of %dth tower\n",search(sum,p,p),x,t);
}
int main()
{
int i;
for(i=0;i<N;i++) num[i]=1,root[i]=i;
scanf("%d",&n);
char cmd[15];
while(n--)
{
scanf("%s",cmd);
if(cmd[0]=='p') put();
else if(cmd[0]=='t'&&cmd[1]=='p') tput();
else if(cmd[0]=='t'&&cmd[1]=='o') towers();
else if(cmd[0]=='c') cubes();
else if(cmd[0]=='l') length();
else if(cmd[0]=='t'&&cmd[1]=='c') tcubes();
}
}