自从暑假洗心革面怒艹数据结构以来,从我手中通过的题,其代码量就基本没低于100行……到现在虽然还有很多题不会搞,却也可以简单地写一些东西,并整理出个可堪一用的板子了。接下来提到的基本是各种树形数据结构的入门级题目和提高级题目,绝大多数来自Damocles数据结构专题训练,主要给队友参考吧。
HDU1754
难度一颗星;单点替换,区间最值。树状数组、线段树、Splay各一发。
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN=200005;
int bit[MAXN],num[MAXN],n;
inline int lowbit(int x) {
return x&-x;
}
void modify(int x,int val) {
num[x]=val;
for(int i=x; i<=n; i+=lowbit(i)) {
bit[i]=max(bit[i],val);
for(int j=1; j<lowbit(i); j<<=1)
bit[i]=max(bit[i],bit[i-j]);
}
}
int query(int L,int R) {
int ret=num[R];
while(true) {
ret=max(ret,num[R]);
if(L==R)
break;
for(R-=1; R-L>=lowbit(R); R-=lowbit(R))
ret=max(ret,bit[R]);
}
return ret;
}
int main() {
int q,a,b;
char op;
while(~scanf("%d%d",&n,&q)) {
memset(bit,0,sizeof(bit));
for(int i=1; i<=n; ++i) {
scanf("%d",&b);
modify(i,b);
}
while(q--) {
scanf(" %c%d%d",&op,&a,&b);
switch(op) {
case 'Q':
printf("%d\n",query(a,b));
break;
case 'U':
modify(a,b);
break;
}
}
}
}
#include<cstdio>
#include<algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int MAXN=200005;
int maxv[MAXN<<2];
void PushUp(int rt) {
maxv[rt]=max(maxv[rt<<1],maxv[rt<<1|1]);
}
void build(int l,int r,int rt) {
if(l==r) {
scanf("%d",&maxv[rt]);
return;
}
int m=l+r>>1;
build(lson);
build(rson);
PushUp(rt);
}
void update(int p,int val,int l,int r,int rt) {
if(l==r) {
maxv[rt]=val;
return;
}
int m=l+r>>1;
if(p<=m)
update(p,val,lson);
else
update(p,val,rson);
PushUp(rt);
}
int query(int L,int R,int l,int r,int rt) {
if(L<=l&&r<=R)
return maxv[rt];
int m=l+r>>1,ret=0;
if(L<=m)
ret=max(ret,query(L,R,lson));
if(m<R)
ret=max(ret,query(L,R,rson));
return ret;
}
int main() {
int n,q,a,b;
char op;
while(~scanf("%d%d",&n,&q)) {
build(1,n,1);
while(q--) {
scanf(" %c%d%d",&op,&a,&b);
switch(op) {
case 'Q':
printf("%d\n",query(a,b,1,n,1));
break;
case 'U':
update(a,b,1,n,1);
break;
}
}
}
}
#include<cstdio>
#include<algorithm>
using namespace std;
#define keyTree ch[ch[root][1]][0]
const int MAXN=200005;
struct Splay {
int tot,root;
int ch[MAXN][2],pre[MAXN],size[MAXN];
void rotate(int x,int f) {
int y=pre[x];
ch[y][f^1]=ch[x][f];
pre[ch[x][f]]=y;
pre[x]=pre[y];
if(pre[x])
ch[pre[y]][ch[pre[y]][1]==y]=x;
ch[x][f]=y;
pre[y]=x;
push_up(y);
}
void splay(int x,int goal) {
while(pre[x]!=goal)
if(pre[pre[x]]==goal)
rotate(x,ch[pre[x]][0]==x);
else {
int y=pre[x],z=pre[y],f=ch[z][0]==y;
if(ch[y][f]==x)
rotate(x,f^1);
else
rotate(y,f);
rotate(x,f);
}
push_up(x);
if(goal==0)
root=x;
}
void rotate_to(int k,int goal) {
int x=root;
while(size[ch[x][0]]!=k)
if(k<size[ch[x][0]])
x=ch[x][0];
else {
k-=size[ch[x][0]]+1;
x=ch[x][1];
}
splay(x,goal);
}
void NewNode(int &x,int c,int fa) {
x=++tot;
ch[x][0]=ch[x][1]=0;
size[x]=1;
pre[x]=fa;
val[x]=vmax[x]=c;
}
void push_up(int x) {
size[x]=size[ch[x][0]]+1+size[ch[x][1]];
vmax[x]=max(val[x],max(vmax[ch[x][0]],vmax[ch[x][1]]));
}
void build(int &x,int l,int r,int f) {
if(l>r)
return;
int m=l+r>>1;
NewNode(x,num[m],f);
build(ch[x][0],l,m-1,x);
build(ch[x][1],m+1,r,x);
push_up(x);
}
void init(int n) {
root=tot=0;
ch[0][0]=ch[0][1]=size[0]=0;
vmax[0]=0;
NewNode(root,-1,0);
NewNode(ch[root][1],-1,root);
size[root]=2;
for(int i=1; i<=n; ++i)
scanf("%d",&num[i]);
build(keyTree,1,n,ch[root][1]);
push_up(ch[root][1]);
push_up(root);
}
void update(int p,int v) {
rotate_to(p-1,0);
rotate_to(p+1,root);
val[keyTree]=v;
vmax[keyTree]=max(vmax[keyTree],v);
}
long long query(int l,int r) {
rotate_to(l-1,0);
rotate_to(r+1,root);
return vmax[keyTree];
}
int num[MAXN],val[MAXN],vmax[MAXN];
} splay;
int main() {
int n,q,a,b;
char op;
while(~scanf("%d%d",&n,&q)) {
splay.init(n);
while(q--) {
scanf(" %c%d%d",&op,&a,&b);
switch(op) {
case 'Q':
printf("%d\n",splay.query(a,b));
break;
case 'U':
splay.update(a,b);
break;
}
}
}
}
POJ3468
难度一星半;区间增减,区间求和,树状数组、线段树、Splay各一发。
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN=100005;
long long bit1[MAXN],bit2[MAXN];
int n;
inline int lowbit(int x) {
return x&-x;
}
void add(int x,int val) {
for(int i=x; i>0; i-=lowbit(i))
bit1[i]+=val;
for(int i=x; i<=n; i+=lowbit(i))
bit2[i]+=x*(long long)val;
}
long long sum(int x) {
if(!x)
return 0;
long long sum1=0,sum2=0;
for(int i=x; i<=n; i+=lowbit(i))
sum1+=bit1[i];
for(int i=x-1; i>0; i-=lowbit(i))
sum2+=bit2[i];
return sum1*x+sum2;
}
int main() {
int q,a,b,c;
char op;
while(~scanf("%d%d",&n,&q)) {
memset(bit1,0,sizeof(bit1));
memset(bit2,0,sizeof(bit2));
for(int i=1; i<=n; ++i) {
scanf("%d",&c);
add(i,c);
if(i>1)
add(i-1,-c);
}
while(q--) {
scanf(" %c%d%d",&op,&a,&b);
switch(op) {
case 'Q':
printf("%I64d\n",sum(b)-sum(a-1));
break;
case 'C':
scanf("%d",&c);
add(b,c);
if(a>1)
add(a-1,-c);
break;
}
}
}
}
#include<cstdio>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int MAXN=100005;
long long sum[MAXN<<2],col[MAXN<<2];
void PushUp(int rt) {
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void PushDown(int rt,int m) {
if(col[rt]) {
col[rt<<1]+=col[rt];
col[rt<<1|1]+=col[rt];
sum[rt<<1]+=col[rt]*(m-(m>>1));
sum[rt<<1|1]+=col[rt]*(m>>1);
col[rt]=0;
}
}
void build(int l,int r,int rt) {
col[rt]=0;
if(l==r) {
scanf("%I64d",&sum[rt]);
return;
}
int m=l+r>>1;
build(lson);
build(rson);
PushUp(rt);
}
void update(int L,int R,int val,int l,int r,int rt) {
if(L<=l&&r<=R) {
col[rt]+=val;
sum[rt]+=val*(r-l+1);
return;
}
PushDown(rt,r-l+1);
int m=l+r>>1;
if(L<=m)
update(L,R,val,lson);
if(m<R)
update(L,R,val,rson);
PushUp(rt);
}
long long query(int L,int R,int l,int r,int rt) {
if(L<=l&&r<=R)
return sum[rt];
PushDown(rt,r-l+1);
int m=l+r>>1;
long long ret=0;
if(L<=m)
ret+=query(L,R,lson);
if(m<R)
ret+=query(L,R,rson);
return ret;
}
int main() {
int n,q,a,b,c;
char op;
while(~scanf("%d%d",&n,&q)) {
build(1,n,1);
while(q--) {
scanf(" %c%d%d",&op,&a,&b);
switch(op) {
case 'Q':
printf("%I64d\n",query(a,b,1,n,1));
break;
case 'C':
scanf("%d",&c);
update(a,b,c,1,n,1);
break;
}
}
}
}
#include<cstdio>
using namespace std;
#define keyTree ch[ch[root][1]][0]
const int MAXN=100005;
struct Splay {
int root,tot;
int ch[MAXN][2],pre[MAXN],size[MAXN];
void rotate(int x,int f) {
int y=pre[x];
ch[y][f^1]=ch[x][f];
pre[ch[x][f]]=y;
pre[x]=pre[y];
if(pre[x])
ch[pre[y]][ch[pre[y]][1]==y]=x;
ch[x][f]=y;
pre[y]=x;
push_up(y);
}
void splay(int x,int goal) {
push_down(x);
while(pre[x]!=goal) {
int y=pre[x],z=pre[y];
if(z==goal) {
push_down(y);
push_down(x);
rotate(x,ch[y][0]==x);
} else {
push_down(z);
push_down(y);
push_down(x);
int f=ch[z][0]==y;
if(ch[y][f]==x)
rotate(x,f^1);
else
rotate(y,f);
rotate(x,f);
}
}
push_up(x);
if(goal==0)
root=x;
}
void rotate_to(int k,int goal) {
int x=root;
push_down(x);
while(size[ch[x][0]]!=k) {
if(k<size[ch[x][0]])
x=ch[x][0];
else {
k-=size[ch[x][0]]+1;
x=ch[x][1];
}
push_down(x);
}
splay(x,goal);
}
void NewNode(int &x,int c,int fa) {
x=++tot;
ch[x][0]=ch[x][1]=0;
pre[x]=fa;
size[x]=1;
val[x]=sum[x]=c;
add[x]=0;
}
void push_up(int x) {
size[x]=size[ch[x][0]]+1+size[ch[x][1]];
sum[x]=val[x]+sum[ch[x][0]]+sum[ch[x][1]];
}
void push_down(int x) {
if(add[x]) {
val[x]+=add[x];
add[ch[x][0]]+=add[x];
add[ch[x][1]]+=add[x];
sum[ch[x][0]]+=(long long)size[ch[x][0]]*add[x];
sum[ch[x][1]]+=(long long)size[ch[x][1]]*add[x];
add[x]=0;
}
}
void build(int &x,int l,int r,int f) {
if(l>r)
return;
int m=l+r>>1;
NewNode(x,num[m],f);
build(ch[x][0],l,m-1,x);
build(ch[x][1],m+1,r,x);
push_up(x);
}
void init(int n) {
root=tot=0;
ch[0][0]=ch[0][1]=size[0]=0;
add[0]=sum[0]=0;
NewNode(root,-1,0);
NewNode(ch[root][1],-1,root);
size[root]=2;
for(int i=1; i<=n; ++i)
scanf("%d",&num[i]);
build(keyTree,1,n,ch[root][1]);
push_up(ch[root][1]);
push_up(root);
}
void update(int l,int r,int v) {
rotate_to(l-1,0);
rotate_to(r+1,root);
add[keyTree]+=v;
sum[keyTree]+=(long long)v*size[keyTree];
}
long long query(int l,int r) {
rotate_to(l-1,0);
rotate_to(r+1,root);
return sum[keyTree];
}
int num[MAXN],val[MAXN],add[MAXN];
long long sum[MAXN];
} splay;
int main() {
int n,q,a,b,c;
char op;
while(~scanf("%d%d",&n,&q)) {
splay.init(n);
while(q--) {
scanf(" %c%d%d",&op,&a,&b);
switch(op) {
case 'Q':
printf("%I64d\n",splay.query(a,b));
break;
case 'C':
scanf("%d",&c);
splay.update(a,b,c);
break;
}
}
}
}
POJ3667
难度两颗星;区间合并。线段树一发。
#include<cstdio>
#include<algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int MAXN=50005;
int cnt[MAXN<<2],lcnt[MAXN<<2],rcnt[MAXN<<2],mark[MAXN<<2];
void push_up(int rt,int len) {
cnt[rt]=max(rcnt[rt<<1]+lcnt[rt<<1|1],max(cnt[rt<<1],cnt[rt<<1|1]));
lcnt[rt]=lcnt[rt<<1];
if(lcnt[rt]==len-(len>>1))
lcnt[rt]+=lcnt[rt<<1|1];
rcnt[rt]=rcnt[rt<<1|1];
if(rcnt[rt]==(len>>1))
rcnt[rt]+=rcnt[rt<<1];
}
void push_down(int rt,int len) {
if(~mark[rt]) {
cnt[rt<<1]=lcnt[rt<<1]=rcnt[rt<<1]=mark[rt]?0:len-(len>>1);
cnt[rt<<1|1]=lcnt[rt<<1|1]=rcnt[rt<<1|1]=mark[rt]?0:(len>>1);
mark[rt<<1]=mark[rt<<1|1]=mark[rt];
mark[rt]=-1;
}
}
void build(int l,int r,int rt) {
mark[rt]=-1;
cnt[rt]=lcnt[rt]=rcnt[rt]=r-l+1;
if(l==r)
return;
int m=l+r>>1;
build(lson);
build(rson);
}
void update(int L,int R,int col,int l,int r,int rt) {
if(L<=l&&r<=R) {
cnt[rt]=lcnt[rt]=rcnt[rt]=col?0:r-l+1;
mark[rt]=col;
return;
}
push_down(rt,r-l+1);
int m=l+r>>1;
if(L<=m)
update(L,R,col,lson);
if(m<R)
update(L,R,col,rson);
push_up(rt,r-l+1);
}
int query(int len,int l,int r,int rt) {
if(cnt[rt]<len)
return 0;
if(l==r)
return l;
push_down(rt,r-l+1);
int m=l+r>>1;
if(cnt[rt<<1]>=len)
return query(len,lson);
else if(rcnt[rt<<1]+lcnt[rt<<1|1]>=len)
return m+1-rcnt[rt<<1];
else if(cnt[rt<<1|1]>=len)
return query(len,rson);
}
int main() {
int n,m,op,x,d,ans;
while(~scanf("%d%d",&n,&m)) {
build(1,n,1);
while(m--) {
scanf("%d",&op);
switch(op) {
case 1:
scanf("%d",&d);
ans=query(d,1,n,1);
printf("%d\n",ans);
if(ans)
update(ans,ans+d-1,1,1,n,1);
break;
case 2:
scanf("%d%d",&x,&d);
update(x,x+d-1,0,1,n,1);
break;
}
}
}
}
HDU2871
难度两星半;区间合并。两种姿势线段树各一发。
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int MAXN=50005;
int cnt[MAXN<<2],lcnt[MAXN<<2],rcnt[MAXN<<2],mark[MAXN<<2];
void push_up(int rt,int len) {
cnt[rt]=max(rcnt[rt<<1]+lcnt[rt<<1|1],max(cnt[rt<<1],cnt[rt<<1|1]));
lcnt[rt]=lcnt[rt<<1];
if(lcnt[rt]==len-(len>>1))
lcnt[rt]+=lcnt[rt<<1|1];
rcnt[rt]=rcnt[rt<<1|1];
if(rcnt[rt]==(len>>1))
rcnt[rt]+=rcnt[rt<<1];
}
void push_down(int rt,int len) {
if(~mark[rt]) {
cnt[rt<<1]=lcnt[rt<<1]=rcnt[rt<<1]=mark[rt]?0:len-(len>>1);
cnt[rt<<1|1]=lcnt[rt<<1|1]=rcnt[rt<<1|1]=mark[rt]?0:(len>>1);
mark[rt<<1]=mark[rt<<1|1]=mark[rt];
mark[rt]=-1;
}
}
void build(int l,int r,int rt) {
mark[rt]=-1;
cnt[rt]=lcnt[rt]=rcnt[rt]=r-l+1;
if(l==r)
return;
int m=l+r>>1;
build(lson);
build(rson);
}
void update(int L,int R,int col,int l,int r,int rt) {
if(L<=l&&r<=R) {
cnt[rt]=lcnt[rt]=rcnt[rt]=col?0:r-l+1;
mark[rt]=col;
return;
}
push_down(rt,r-l+1);
int m=l+r>>1;
if(L<=m)
update(L,R,col,lson);
if(m<R)
update(L,R,col,rson);
push_up(rt,r-l+1);
}
int query(int len,int l,int r,int rt) {
if(l==r)
return l;
push_down(rt,r-l+1);
int m=l+r>>1;
if(cnt[rt<<1]>=len)
return query(len,lson);
else if(rcnt[rt<<1]+lcnt[rt<<1|1]>=len)
return m+1-rcnt[rt<<1];
else if(cnt[rt<<1|1]>=len)
return query(len,rson);
}
vector<pair<int,int> > block;
vector<pair<int,int> >::iterator it;
int main() {
int n,m,x,a;
char op[8];
pair<int,int> tmp;
while(~scanf("%d%d",&n,&m)) {
build(1,n,1);
block.clear();
while(m--) {
scanf("%s",op);
switch(op[0]) {
case 'R':
update(1,n,0,1,n,1);
block.clear();
puts("Reset Now");
break;
case 'N':
scanf("%d",&x);
if(cnt[1]>=x) {
a=query(x,1,n,1);
update(a,a+x-1,1,1,n,1);
tmp=make_pair(a,a+x-1);
it=upper_bound(block.begin(),block.end(),tmp);
block.insert(it,tmp);
printf("New at %d\n",a);
} else
puts("Reject New");
break;
case 'F':
scanf("%d",&x);
it=upper_bound(block.begin(),block.end(),make_pair(x,n+1));
if(it==block.begin())
puts("Reject Free");
else {
--it;
if(it->second<x)
puts("Reject Free");
else {
update(it->first,it->second,0,1,n,1);
printf("Free from %d to %d\n",it->first,it->second);
block.erase(it);
}
}
break;
case 'G':
scanf("%d",&x);
if(x<=block.size())
printf("Get at %d\n",block[x-1].first);
else
puts("Reject Get");
break;
}
}
putchar('\n');
}
}
#include<cstdio>
#include<algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int MAXN=50005;
int cnt[MAXN<<2],lcnt[MAXN<<2],rcnt[MAXN<<2],mark[MAXN<<2],start[MAXN<<2],end[MAXN<<2],num[MAXN<<2];
bool cover[MAXN<<2];
void push_up(int rt,int len) {
cnt[rt]=max(rcnt[rt<<1]+lcnt[rt<<1|1],max(cnt[rt<<1],cnt[rt<<1|1]));
lcnt[rt]=lcnt[rt<<1];
if(lcnt[rt]==len-(len>>1))
lcnt[rt]+=lcnt[rt<<1|1];
rcnt[rt]=rcnt[rt<<1|1];
if(rcnt[rt]==(len>>1))
rcnt[rt]+=rcnt[rt<<1];
}
void push_down(int rt,int len) {
if(~mark[rt]) {
cnt[rt<<1]=lcnt[rt<<1]=rcnt[rt<<1]=mark[rt]?0:len-(len>>1);
cnt[rt<<1|1]=lcnt[rt<<1|1]=rcnt[rt<<1|1]=mark[rt]?0:(len>>1);
start[rt<<1]=start[rt<<1|1]=start[rt];
end[rt<<1]=end[rt<<1|1]=end[rt];
mark[rt<<1]=mark[rt<<1|1]=mark[rt];
mark[rt]=-1;
}
}
void update(int L,int R,int col,int l,int r,int rt) {
if(L<=l&&r<=R) {
cnt[rt]=lcnt[rt]=rcnt[rt]=col?0:r-l+1;
mark[rt]=col;
if(col) {
start[rt]=L;
end[rt]=R;
} else
start[rt]=end[rt]=-1;
return;
}
push_down(rt,r-l+1);
int m=l+r>>1;
if(L<=m)
update(L,R,col,lson);
if(m<R)
update(L,R,col,rson);
push_up(rt,r-l+1);
}
int New(int len,int l,int r,int rt) {
if(l==r)
return l;
push_down(rt,r-l+1);
int m=l+r>>1;
if(cnt[rt<<1]>=len)
return New(len,lson);
else if(rcnt[rt<<1]+lcnt[rt<<1|1]>=len)
return m+1-rcnt[rt<<1];
else if(cnt[rt<<1|1]>=len)
return New(len,rson);
}
int Free(int p,int l,int r,int rt) {
if(l==r)
return rt;
push_down(rt,r-l+1);
int m=l+r>>1;
if(p<=m)
return Free(p,lson);
else
return Free(p,rson);
}
void count_up(int rt) {
num[rt]=num[rt<<1]+num[rt<<1|1];
}
void count_down(int rt) {
if(cover[rt]) {
num[rt<<1]=num[rt<<1|1]=0;
cover[rt<<1]=cover[rt<<1|1]=cover[rt];
cover[rt]=false;
}
}
void count(int p,int val,int l,int r,int rt) {
if(l==r) {
num[rt]=val;
return;
}
count_down(rt);
int m=l+r>>1;
if(p<=m)
count(p,val,lson);
else
count(p,val,rson);
count_up(rt);
}
int Get(int k,int l,int r,int rt) {
if(l==r)
return l;
int m=l+r>>1;
count_down(rt);
if(num[rt<<1]>=k)
return Get(k,lson);
else
return Get(k-num[rt<<1],rson);
}
int main() {
int n,m,x,a;
char op[8];
while(~scanf("%d%d",&n,&m)) {
update(1,n,0,1,n,1);
cover[1]=true;
num[1]=0;
while(m--) {
scanf("%s",op);
switch(op[0]) {
case 'R':
puts("Reset Now");
update(1,n,0,1,n,1);
cover[1]=true;
num[1]=0;
break;
case 'N':
scanf("%d",&x);
if(cnt[1]>=x) {
a=New(x,1,n,1);
printf("New at %d\n",a);
count(a,1,1,n,1);
update(a,a+x-1,1,1,n,1);
} else
puts("Reject New");
break;
case 'F':
scanf("%d",&x);
a=Free(x,1,n,1);
if(~start[a]) {
printf("Free from %d to %d\n",start[a],end[a]);
count(start[a],0,1,n,1);
update(start[a],end[a],0,1,n,1);
} else
puts("Reject Free");
break;
case 'G':
scanf("%d",&x);
if(num[1]>=x)
printf("Get at %d\n",Get(x,1,n,1));
else
puts("Reject Get");
break;
}
}
putchar('\n');
}
}
HDU4902
难度两星半;区间带限制覆盖,区间最值,多重lazy标记。线段树一发。
#include<cstdio>
#include<algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int N=100005;
int cover[N<<2],vmax[N<<2];
bool same[N<<2];
void push_up(int rt) {
vmax[rt]=max(vmax[rt<<1],vmax[rt<<1|1]);
same[rt]=same[rt<<1]&&same[rt<<1|1]&&vmax[rt<<1]==vmax[rt<<1|1];
}
void push_down(int rt) {
if(cover[rt]) {
vmax[rt<<1]=vmax[rt<<1|1]=cover[rt<<1]=cover[rt<<1|1]=cover[rt];
cover[rt]=0;
}
if(same[rt])
same[rt<<1]=same[rt<<1|1]=true;
}
void build(int l,int r,int rt) {
cover[rt]=0;
same[rt]=false;
if(l==r) {
scanf("%d",&vmax[rt]);
return;
}
int m=l+r>>1;
build(lson);
build(rson);
push_up(rt);
}
void upcover(int L,int R,int v,int l,int r,int rt) {
if(L<=l&&r<=R) {
vmax[rt]=cover[rt]=v;
same[rt]=true;
return;
}
push_down(rt);
int m=l+r>>1;
if(L<=m)
upcover(L,R,v,lson);
if(m<R)
upcover(L,R,v,rson);
push_up(rt);
}
void upgcd(int L,int R,int v,int l,int r,int rt) {
if(vmax[rt]<=v)
return;
if(l==r||(L<=l&&r<=R&&same[rt])) {
cover[rt]=vmax[rt]=__gcd(vmax[rt],v);
same[rt]=true;
return;
}
push_down(rt);
int m=l+r>>1;
if(L<=m)
upgcd(L,R,v,lson);
if(m<R)
upgcd(L,R,v,rson);
push_up(rt);
}
int query(int p,int l,int r,int rt) {
if(l==r)
return vmax[rt];
push_down(rt);
int m=l+r>>1;
if(p<=m)
return query(p,lson);
else
return query(p,rson);
}
int main() {
int T,n,q,a,t,l,r,x;
scanf("%d",&T);
while(T--) {
scanf("%d",&n);
build(1,n,1);
scanf("%d",&q);
while(q--) {
scanf("%d%d%d%d",&t,&l,&r,&x);
switch(t) {
case 1:
upcover(l,r,x,1,n,1);
break;
case 2:
upgcd(l,r,x,1,n,1);
break;
}
}
for(int i=1; i<=n; ++i)
printf("%d ",query(i,1,n,1));
putchar('\n');
}
}
HDU4819
难度三颗星;二维平面单点修改,区间最值。四分树、二维线段树各一发。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define tl xl,xm,yl,ym,rt<<2
#define tr xl,xm,ym+1,yr,(rt<<2)+1
#define dl xm+1,xr,yl,ym,(rt<<2)+2
#define dr xm+1,xr,ym+1,yr,(rt<<2)+3
const int MAXN=805;
const int INF=0x3f3f3f3f;
int vmax[MAXN<<12],vmin[MAXN<<12];
void push_up(int rt) {
vmax[rt]=max(max(vmax[rt<<2],vmax[(rt<<2)+1]),max(vmax[(rt<<2)+2],vmax[(rt<<2)+3]));
vmin[rt]=min(min(vmin[rt<<2],vmin[(rt<<2)+1]),min(vmin[(rt<<2)+2],vmin[(rt<<2)+3]));
}
void update(int x,int y,int v,int xl,int xr,int yl,int yr,int rt) {
if(xl==xr&&yl==yr) {
vmax[rt]=vmin[rt]=v;
return;
}
int xm=xl+xr>>1,ym=yl+yr>>1;
if(x<=xm) {
if(y<=ym)
update(x,y,v,tl);
else
update(x,y,v,tr);
} else {
if(y<=ym)
update(x,y,v,dl);
else
update(x,y,v,dr);
}
push_up(rt);
}
pair<int,int> query(int xL,int xR,int yL,int yR,int xl,int xr,int yl,int yr,int rt) {
if(xL<=xl&&xr<=xR&&yL<=yl&&yr<=yR)
return make_pair(vmax[rt],vmin[rt]);
int xm=xl+xr>>1,ym=yl+yr>>1,retmax=0,retmin=INF;
pair<int,int> tmp;
if(xL<=xm&&yL<=ym) {
tmp=query(xL,xR,yL,yR,tl);
retmax=max(retmax,tmp.first);
retmin=min(retmin,tmp.second);
}
if(xL<=xm&&yR>ym) {
tmp=query(xL,xR,yL,yR,tr);
retmax=max(retmax,tmp.first);
retmin=min(retmin,tmp.second);
}
if(xR>xm&&yL<=ym) {
tmp=query(xL,xR,yL,yR,dl);
retmax=max(retmax,tmp.first);
retmin=min(retmin,tmp.second);
}
if(xR>xm&&yR>ym) {
tmp=query(xL,xR,yL,yR,dr);
retmax=max(retmax,tmp.first);
retmin=min(retmin,tmp.second);
}
return make_pair(retmax,retmin);
}
int main() {
int t,n,v,q,x,y,l;
scanf("%d",&t);
for(int cas=1; cas<=t; ++cas) {
scanf("%d",&n);
memset(vmax,0,sizeof(vmax));
memset(vmin,0x3f,sizeof(vmin));
for(int i=1; i<=n; ++i)
for(int j=1; j<=n; ++j) {
scanf("%d",&v);
update(i,j,v,1,n,1,n,1);
}
scanf("%d",&q);
printf("Case #%d:\n",cas);
while(q--) {
scanf("%d%d%d",&x,&y,&l);
pair<int,int> ans=query(max(x-l/2,1),min(x+l/2,n),max(y-l/2,1),min(y+l/2,n),1,n,1,n,1);
printf("%d\n",(ans.first+ans.second)/2);
update(x,y,(ans.first+ans.second)/2,1,n,1,n,1);
}
}
}
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int MAXN=805;
const int INF=0x3f3f3f3f;
int vmax[MAXN<<2][MAXN<<2],vmin[MAXN<<2][MAXN<<2],n;
void push_up(int x,int rt) {
vmax[x][rt]=max(vmax[x][rt<<1],vmax[x][rt<<1|1]);
vmin[x][rt]=min(vmin[x][rt<<1],vmin[x][rt<<1|1]);
}
void push_up1(int x,int rt) {
vmax[x][rt]=max(vmax[x<<1][rt],vmax[x<<1|1][rt]);
vmin[x][rt]=min(vmin[x<<1][rt],vmin[x<<1|1][rt]);
}
void build(int x,int l,int r,int rt) {
vmax[x][rt]=0;
vmin[x][rt]=INF;
if(l==r)
return;
int m=l+r>>1;
build(x,lson);
build(x,rson);
}
void build(int l,int r,int rt) {
if(l==r) {
build(rt,1,n,1);
return;
}
int m=l+r>>1;
build(lson);
build(rson);
}
void update2(int x,int p,int v,int l,int r,int rt) {
if(l==r) {
vmax[x][rt]=vmin[x][rt]=v;
return;
}
int m=l+r>>1;
if(p<=m)
update2(x,p,v,lson);
else
update2(x,p,v,rson);
push_up(x,rt);
}
void update1(int x,int p,int v,int l,int r,int rt) {
if(l==r) {
push_up1(x,rt);
return;
}
int m=l+r>>1;
if(p<=m)
update1(x,p,v,lson);
else
update1(x,p,v,rson);
push_up(x,rt);
}
void update(int p,int q,int v,int l,int r,int rt) {
if(l==r) {
update2(rt,q,v,1,n,1);
return;
}
int m=l+r>>1;
if(p<=m)
update(p,q,v,lson);
else
update(p,q,v,rson);
update1(rt,q,v,1,n,1);
}
pair<int,int> query(int x,int L,int R,int l,int r,int rt) {
if(L<=l&&r<=R)
return make_pair(vmax[x][rt],vmin[x][rt]);
int m=l+r>>1,retmax=0,retmin=INF;
pair<int,int> tmp;
if(L<=m) {
tmp=query(x,L,R,lson);
retmax=max(retmax,tmp.first);
retmin=min(retmin,tmp.second);
}
if(m<R) {
tmp=query(x,L,R,rson);
retmax=max(retmax,tmp.first);
retmin=min(retmin,tmp.second);
}
return make_pair(retmax,retmin);
}
pair<int,int> query(int xL,int xR,int yL,int yR,int l,int r,int rt) {
if(xL<=l&&r<=xR)
return query(rt,yL,yR,1,n,1);
int m=l+r>>1,retmax=0,retmin=INF;
pair<int,int> tmp;
if(xL<=m) {
tmp=query(xL,xR,yL,yR,lson);
retmax=max(retmax,tmp.first);
retmin=min(retmin,tmp.second);
}
if(m<xR) {
tmp=query(xL,xR,yL,yR,rson);
retmax=max(retmax,tmp.first);
retmin=min(retmin,tmp.second);
}
return make_pair(retmax,retmin);
}
int main() {
int t,v,q,x,y,l;
scanf("%d",&t);
for(int cas=1; cas<=t; ++cas) {
scanf("%d",&n);
build(1,n,1);
for(int i=1; i<=n; ++i)
for(int j=1; j<=n; ++j) {
scanf("%d",&v);
update(i,j,v,1,n,1);
}
scanf("%d",&q);
printf("Case #%d:\n",cas);
while(q--) {
scanf("%d%d%d",&x,&y,&l);
pair<int,int> ans=query(max(x-l/2,1),min(x+l/2,n),max(y-l/2,1),min(y+l/2,n),1,n,1);
printf("%d\n",(ans.first+ans.second)/2);
update(x,y,(ans.first+ans.second)/2,1,n,1);
}
}
}
POJ3321
难度两颗星;树上单点修改,子树求和。树上dfs序+树状数组、树上dfs序+线段树各一发。
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN=1000005;
const int MAXM=MAXN;
struct graph {
int head[MAXN];
int to[MAXM],next[MAXM];
int tot;
void init() {
tot=0;
memset(head,0xff,sizeof(head));
}
void add(int u,int v) {
to[tot]=v;
next[tot]=head[u];
head[u]=tot++;
}
} g;
int bit[MAXN],n;
inline int lowbit(int x) {
return x&-x;
}
void add(int x,int val) {
for(int i=x; i<=n; i+=lowbit(i))
bit[i]+=val;
}
int sum(int x) {
int ret=0;
for(int i=x; i>0; i-=lowbit(i))
ret+=bit[i];
return ret;
}
int low[MAXN],high[MAXN],cnt;
void dfs(int u) {
low[u]=++cnt;
for(int i=g.head[u]; ~i; i=g.next[i])
dfs(g.to[i]);
high[u]=cnt;
}
int main() {
int u,v,m,x;
char op;
while(~scanf("%d",&n)) {
g.init();
for(int i=1; i<n; ++i) {
scanf("%d%d",&u,&v);
g.add(u,v);
}
cnt=0;
dfs(1);
memset(bit,0,sizeof(bit));
for(int i=1; i<=n; ++i)
add(i,1);
scanf("%d",&m);
while(m--) {
scanf(" %c%d",&op,&x);
switch(op) {
case 'C':
add(low[x],!(sum(low[x])-sum(low[x]-1))?1:-1);
break;
case 'Q':
printf("%d\n",sum(high[x])-sum(low[x]-1));
break;
}
}
}
}
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN=1000005;
const int MAXM=MAXN;
struct graph {
int head[MAXN];
int to[MAXM],next[MAXM];
int tot;
void init() {
tot=0;
memset(head,0xff,sizeof(head));
}
void add(int u,int v) {
to[tot]=v;
next[tot]=head[u];
head[u]=tot++;
}
} g;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int sum[MAXN<<2];
void push_up(int rt) {
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void build(int l,int r,int rt) {
if(l==r) {
sum[rt]=1;
return;
}
int m=l+r>>1;
build(lson);
build(rson);
push_up(rt);
}
void update(int p,int val,int l,int r,int rt) {
if(l==r) {
sum[rt]+=val;
return;
}
int m=l+r>>1;
if(p<=m)
update(p,val,lson);
else
update(p,val,rson);
push_up(rt);
}
int query(int L,int R,int l,int r,int rt) {
if(L<=l&&r<=R)
return sum[rt];
int m=l+r>>1,ret=0;
if(L<=m)
ret+=query(L,R,lson);
if(m<R)
ret+=query(L,R,rson);
return ret;
}
int low[MAXN],high[MAXN],cnt;
void dfs(int u) {
low[u]=++cnt;
for(int i=g.head[u]; ~i; i=g.next[i])
dfs(g.to[i]);
high[u]=cnt;
}
int main() {
int n,u,v,m,x;
char op;
while(~scanf("%d",&n)) {
g.init();
for(int i=1; i<n; ++i) {
scanf("%d%d",&u,&v);
g.add(u,v);
}
cnt=0;
dfs(1);
build(1,n,1);
scanf("%d",&m);
while(m--) {
scanf(" %c%d",&op,&x);
switch(op) {
case 'C':
update(low[x],!query(low[x],low[x],1,n,1)?1:-1,1,n,1);
break;
case 'Q':
printf("%d\n",query(low[x],high[x],1,n,1));
break;
}
}
}
}
HDU3887
难度两星半;树上单点修改,子树带限制求和。树上dfs序+树状数组、树上dfs序+线段树各一发。
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
const int MAXN=100005;
const int MAXM=MAXN<<1;
struct graph {
int head[MAXN];
int to[MAXM],next[MAXM];
int tot;
void init() {
tot=0;
memset(head,0xff,sizeof(head));
}
void add(int u,int v) {
to[tot]=v;
next[tot]=head[u];
head[u]=tot++;
}
} g;
int bit[MAXN],n;
inline int lowbit(int x) {
return x&-x;
}
void add(int x,int val) {
for(int i=x; i<=n; i+=lowbit(i))
bit[i]+=val;
}
int sum(int x) {
int ret=0;
for(int i=x; i>0; i-=lowbit(i))
ret+=bit[i];
return ret;
}
int ans[MAXN];
void dfs(int u,int pre) {
add(u,1);
ans[u]=sum(u);
for(int i=g.head[u]; ~i; i=g.next[i]) {
int v=g.to[i];
if(v!=pre)
dfs(v,u);
}
ans[u]=sum(u)-ans[u];
}
int main() {
int __size__=16<<20;
char *__p__=(char*)malloc(__size__)+__size__;
__asm__("movl %0, %%esp\n"::"r"(__p__));
int p,u,v;
while(~scanf("%d%d",&n,&p)&&(n||p)) {
g.init();
for(int i=1; i<n; ++i) {
scanf("%d%d",&u,&v);
g.add(u,v);
g.add(v,u);
}
memset(bit,0,sizeof(bit));
dfs(p,-1);
for(int i=1; i<=n; ++i) {
printf("%d",ans[i]);
putchar(i<n?' ':'\n');
}
}
}
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
const int MAXN=100005;
const int MAXM=MAXN<<1;
struct graph {
int head[MAXN];
int to[MAXM],next[MAXM];
int tot;
void init() {
tot=0;
memset(head,0xff,sizeof(head));
}
void add(int u,int v) {
to[tot]=v;
next[tot]=head[u];
head[u]=tot++;
}
} g;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int sum[MAXN<<2];
void build(int l,int r,int rt) {
sum[rt]=0;
if(l==r)
return;
int m=l+r>>1;
build(lson);
build(rson);
}
void update(int p,int val,int l,int r,int rt) {
if(l==r) {
sum[rt]+=val;
return;
}
int m=l+r>>1;
if(p<=m)
update(p,val,lson);
else
update(p,val,rson);
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
int query(int L,int R,int l,int r,int rt) {
if(L<=l&&r<=R)
return sum[rt];
int m=l+r>>1,ret=0;
if(L<=m)
ret+=query(L,R,lson);
if(m<R)
ret+=query(L,R,rson);
return ret;
}
int ans[MAXN],n;
void dfs(int u,int pre) {
update(u,1,1,n,1);
ans[u]=query(1,u,1,n,1);
for(int i=g.head[u]; ~i; i=g.next[i]) {
int v=g.to[i];
if(v!=pre)
dfs(v,u);
}
ans[u]=query(1,u,1,n,1)-ans[u];
}
int main() {
int __size__=16<<20;
char *__p__=(char*)malloc(__size__)+__size__;
__asm__("movl %0, %%esp\n"::"r"(__p__));
int p,u,v;
while(~scanf("%d%d",&n,&p)&&(n||p)) {
g.init();
for(int i=1; i<n; ++i) {
scanf("%d%d",&u,&v);
g.add(u,v);
g.add(v,u);
}
build(1,n,1);
dfs(p,-1);
for(int i=1; i<=n; ++i) {
printf("%d",ans[i]);
putchar(i<n?' ':'\n');
}
}
}
HDU3966
难度三颗星;树上路径修改,单点查询。树上dfs序+LCA+树状数组、树链剖分+树状数组、树链剖分+线段树各一发。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=50005;
const int MAXM=MAXN<<1;
struct graph {
int head[MAXN];
int to[MAXM],next[MAXM];
int tot;
void init() {
tot=0;
memset(head,0xff,sizeof(head));
}
void add(int u,int v) {
to[tot]=v;
next[tot]=head[u];
head[u]=tot++;
}
} g;
const int maxd=18;
int low[MAXN],high[MAXN],cnt;
int d[MAXN],f[MAXN][maxd];
void dfs(int u,int fa) {
low[u]=++cnt;
f[u][0]=fa;
d[u]=d[fa]+1;
for(int i=1; i<maxd; ++i)
f[u][i]=f[f[u][i-1]][i-1];
for(int i=g.head[u]; ~i; i=g.next[i]) {
int v=g.to[i];
if(v!=fa)
dfs(v,u);
}
high[u]=++cnt;
}
int lca(int u,int v) {
if(d[u]<d[v])
swap(u,v);
int k=d[u]-d[v];
for(int i=0; i<maxd; ++i)
if((1<<i)&k)
u=f[u][i];
if(u==v)
return u;
for(int i=maxd-1; i>=0; --i)
if(f[u][i]!=f[v][i]) {
u=f[u][i];
v=f[v][i];
}
return f[u][0];
}
int bit[MAXN<<1];
inline int lowbit(int x) {
return x&-x;
}
void add(int x,int val) {
for(int i=x; i>0; i-=lowbit(i))
bit[i]+=val;
}
int get(int x) {
int ret=0;
for(int i=x; i<=cnt; i+=lowbit(i))
ret+=bit[i];
return ret;
}
void modify(int x,int y,int d) {
add(low[x],d);
add(low[y],d);
int fa=lca(x,y);
add(low[fa]-1,-d);
add(low[fa],-d);
}
int a[MAXN];
int main() {
int n,m,p,u,v,c,k;
char op;
while(~scanf("%d%d%d",&n,&m,&p)) {
for(int i=1; i<=n; ++i)
scanf("%d",&a[i]);
g.init();
while(m--) {
scanf("%d%d",&u,&v);
g.add(u,v);
g.add(v,u);
}
cnt=0;
dfs(1,-1);
memset(bit,0,sizeof(bit));
while(p--) {
scanf(" %c",&op);
switch(op) {
case 'I':
scanf("%d%d%d",&u,&v,&k);
modify(u,v,k);
break;
case 'D':
scanf("%d%d%d",&u,&v,&k);
modify(u,v,-k);
break;
case 'Q':
scanf("%d",&c);
printf("%d\n",a[c]+get(low[c])-get(high[c]));
break;
}
}
}
}
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=50005;
const int MAXM=MAXN<<1;
struct graph {
int head[MAXN];
int to[MAXM],next[MAXM];
int tot;
void init() {
tot=0;
memset(head,0xff,sizeof(head));
}
void add(int u,int v) {
to[tot]=v;
next[tot]=head[u];
head[u]=tot++;
}
} g;
int top[MAXN],len[MAXN];
int belong[MAXN],idx[MAXN];
int dep[MAXN],fa[MAXN],size[MAXN];
int que[MAXN];
bool vis[MAXN];
int n,cnt;
void split() {
memset(dep,0xff,sizeof(dep));
int l=0,r=0;
que[++r]=1;
dep[1]=0;
fa[1]=-1;
while(l<r) {
int u=que[++l];
vis[u]=false;
for(int i=g.head[u]; ~i; i=g.next[i]) {
int v=g.to[i];
if(!~dep[v]) {
que[++r]=v;
dep[v]=dep[u]+1;
fa[v]=u;
}
}
}
cnt=0;
for(int i=n; i>0; --i) {
int u=que[i],p=-1;
size[u]=1;
for(int j=g.head[u]; ~j; j=g.next[j]) {
int v=g.to[j];
if(vis[v]) {
size[u]+=size[v];
if(!~p||size[v]>size[p])
p=v;
}
}
if(!~p) {
idx[u]=len[++cnt]=1;
belong[u]=cnt;
top[cnt]=u;
} else {
belong[u]=belong[p];
idx[u]=++len[belong[u]];
top[belong[u]]=u;
}
vis[u]=true;
}
}
int fi[MAXN],cid[MAXN],rank[MAXN];
void getcid() {
fi[1]=1;
for(int i=2; i<=cnt; ++i)
fi[i]=fi[i-1]+len[i-1];
for(int i=1; i<=n; ++i) {
cid[i]=fi[belong[i]]+len[belong[i]]-idx[i];
rank[cid[i]]=i;
}
}
int bit[MAXN];
inline int lowbit(int x) {
return x&-x;
}
void add(int x,int val) {
for(int i=x; i>0; i-=lowbit(i))
bit[i]+=val;
}
int sum(int x) {
int ret=0;
for(int i=x; i<=n; i+=lowbit(i))
ret+=bit[i];
return ret;
}
void modify(int x,int y,int d) {
while(belong[x]!=belong[y]) {
if(dep[top[belong[x]]]<dep[top[belong[y]]])
swap(x,y);
add(cid[top[belong[x]]]-1,-d);
add(cid[x],d);
x=fa[top[belong[x]]];
}
if(dep[x]>dep[y])
swap(x,y);
add(cid[x]-1,-d);
add(cid[y],d);
}
int a[MAXN];
int main() {
int m,p,u,v,c,k;
char op;
while(~scanf("%d%d%d",&n,&m,&p)) {
for(int i=1; i<=n; ++i)
scanf("%d",&a[i]);
g.init();
while(m--) {
scanf("%d%d",&u,&v);
g.add(u,v);
g.add(v,u);
}
split();
getcid();
memset(bit,0,sizeof(bit));
while(p--) {
scanf(" %c",&op);
switch(op) {
case 'I':
scanf("%d%d%d",&u,&v,&k);
modify(u,v,k);
break;
case 'D':
scanf("%d%d%d",&u,&v,&k);
modify(u,v,-k);
break;
case 'Q':
scanf("%d",&c);
printf("%d\n",a[c]+sum(cid[c]));
break;
}
}
}
}
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=50005;
const int MAXM=MAXN<<1;
struct graph {
int head[MAXN];
int to[MAXM],next[MAXM];
int tot;
void init() {
tot=0;
memset(head,0xff,sizeof(head));
}
void add(int u,int v) {
to[tot]=v;
next[tot]=head[u];
head[u]=tot++;
}
} g;
int top[MAXN],len[MAXN];
int belong[MAXN],idx[MAXN];
int dep[MAXN],fa[MAXN],size[MAXN];
int que[MAXN];
bool vis[MAXN];
int n,cnt;
void split() {
memset(dep,0xff,sizeof(dep));
int l=0,r=0;
que[++r]=1;
dep[1]=0;
fa[1]=-1;
while(l<r) {
int u=que[++l];
vis[u]=false;
for(int i=g.head[u]; ~i; i=g.next[i]) {
int v=g.to[i];
if(!~dep[v]) {
que[++r]=v;
dep[v]=dep[u]+1;
fa[v]=u;
}
}
}
cnt=0;
for(int i=n; i>0; --i) {
int u=que[i],p=-1;
size[u]=1;
for(int j=g.head[u]; ~j; j=g.next[j]) {
int v=g.to[j];
if(vis[v]) {
size[u]+=size[v];
if(!~p||size[v]>size[p])
p=v;
}
}
if(!~p) {
idx[u]=len[++cnt]=1;
belong[u]=cnt;
top[cnt]=u;
} else {
belong[u]=belong[p];
idx[u]=++len[belong[u]];
top[belong[u]]=u;
}
vis[u]=true;
}
}
int a[MAXN],fi[MAXN],cid[MAXN],rank[MAXN];
void getcid() {
fi[1]=1;
for(int i=2; i<=cnt; ++i)
fi[i]=fi[i-1]+len[i-1];
for(int i=1; i<=n; ++i) {
cid[i]=fi[belong[i]]+len[belong[i]]-idx[i];
rank[cid[i]]=i;
}
}
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int sum[MAXN<<2],col[MAXN<<2];
void push_up(int rt) {
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void push_down(int rt,int len) {
if(col[rt]) {
col[rt<<1]+=col[rt];
col[rt<<1|1]+=col[rt];
sum[rt<<1]+=col[rt]*(len-(len>>1));
sum[rt<<1|1]+=col[rt]*(len>>1);
col[rt]=0;
}
}
void build(int l,int r,int rt) {
col[rt]=0;
if(l==r) {
sum[rt]=a[rank[l]];
return;
}
int m=l+r>>1;
build(lson);
build(rson);
push_up(rt);
}
void update(int L,int R,int val,int l,int r,int rt) {
if(L<=l&&r<=R) {
col[rt]+=val;
sum[rt]+=val*(r-l+1);
return;
}
push_down(rt,r-l+1);
int m=l+r>>1;
if(L<=m)
update(L,R,val,lson);
if(m<R)
update(L,R,val,rson);
push_up(rt);
}
int query(int p,int l,int r,int rt) {
if(l==r)
return sum[rt];
push_down(rt,r-l+1);
int m=l+r>>1;
if(p<=m)
return query(p,lson);
else
return query(p,rson);
}
void modify(int x,int y,int d) {
while(belong[x]!=belong[y]) {
if(dep[top[belong[x]]]<dep[top[belong[y]]])
swap(x,y);
update(cid[top[belong[x]]],cid[x],d,1,n,1);
x=fa[top[belong[x]]];
}
if(dep[x]>dep[y])
swap(x,y);
update(cid[x],cid[y],d,1,n,1);
}
int main() {
int m,p,u,v,c,k;
char op;
while(~scanf("%d%d%d",&n,&m,&p)) {
for(int i=1; i<=n; ++i)
scanf("%d",&a[i]);
g.init();
while(m--) {
scanf("%d%d",&u,&v);
g.add(u,v);
g.add(v,u);
}
split();
getcid();
build(1,n,1);
while(p--) {
scanf(" %c",&op);
switch(op) {
case 'I':
scanf("%d%d%d",&u,&v,&k);
modify(u,v,k);
break;
case 'D':
scanf("%d%d%d",&u,&v,&k);
modify(u,v,-k);
break;
case 'Q':
scanf("%d",&c);
printf("%d\n",query(cid[c],1,n,1));
break;
}
}
}
}
POJ3481
难度一颗星;平衡树插入、删除。Treap、Size Balanced Tree、Skip List各一发。
#include<cstdio>
#include<cstdlib>
using namespace std;
const int MAXN=1000005;
const int INF=0x3f3f3f3f;
struct Treap {
int tot,root;
int ch[MAXN][2],key[MAXN],pt[MAXN],size[MAXN],val[MAXN];
Treap() {
tot=1;
root=0;
pt[0]=INF;
size[0]=0;
}
void rotate(int &x,int t) {
int y=ch[x][t];
ch[x][t]=ch[y][t^1];
ch[y][t^1]=x;
size[y]=size[x];
size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
x=y;
}
bool insert(int &x,int k,int v) {
if(!x) {
x=tot++;
ch[x][0]=ch[x][1]=0;
key[x]=k;
val[x]=v;
pt[x]=rand();
size[x]=1;
return true;
}
if(key[x]==k)
return false;
int t=key[x]<k;
if(!insert(ch[x][t],k,v))
return false;
++size[x];
if(pt[ch[x][t]]<pt[x])
rotate(x,t);
return true;
}
bool erase(int &x,int k) {
if(!x)
return false;
if(key[x]!=k) {
if(!erase(ch[x][key[x]<k],k))
return false;
--size[x];
} else if(!ch[x][0]&&!ch[x][1])
x=0;
else if(!ch[x][0])
x=ch[x][1];
else if(!ch[x][1])
x=ch[x][0];
else {
rotate(x,pt[ch[x][0]]>pt[ch[x][1]]);
if(!erase(ch[x][key[x]<k],k))
return false;
--size[x];
}
return true;
}
void insert(int k,int v) {
insert(root,k,v);
}
void erase(int k) {
erase(root,k);
}
int getMin(int x) {
while(ch[x][0])
x=ch[x][0];
return x;
}
int getMax(int x) {
while(ch[x][1])
x=ch[x][1];
return x;
}
int getLow() {
if(size[root]==0)
return 0;
int x=getMin(root),ret=val[x];
erase(key[x]);
return ret;
}
int getHigh() {
if(size[root]==0)
return 0;
int x=getMax(root),ret=val[x];
erase(key[x]);
return ret;
}
} treap;
int main() {
int op,k,p;
while(~scanf("%d",&op)&&op)
switch(op) {
case 1:
scanf("%d%d",&k,&p);
treap.insert(p,k);
break;
case 2:
printf("%d\n",treap.getHigh());
break;
case 3:
printf("%d\n",treap.getLow());
break;
}
}
#include<cstdio>
using namespace std;
const int MAXN=1000005;
struct SBT {
int root,tot;
int ch[MAXN][2],key[MAXN],size[MAXN],val[MAXN];
SBT() {
tot=1;
root=0;
size[0]=0;
}
void rotate(int &x,int t) {
int y=ch[x][t];
ch[x][t]=ch[y][t^1];
ch[y][t^1]=x;
size[y]=size[x];
size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
x=y;
}
void Maintain(int &x,int t) {
if(size[ch[ch[x][t]][t]]>size[ch[x][t^1]])
rotate(x,t);
else if(size[ch[ch[x][t]][t^1]]>size[ch[x][t^1]]) {
rotate(ch[x][t],t^1);
rotate(x,t);
} else
return;
Maintain(ch[x][0],0);
Maintain(ch[x][1],1);
Maintain(x,0);
Maintain(x,1);
}
void insert(int &x,int k,int v) {
if(x==0) {
x=tot++;
ch[x][0]=ch[x][1]=0;
key[x]=k;
val[x]=v;
size[x]=1;
} else {
++size[x];
insert(ch[x][k>=key[x]],k,v);
Maintain(x,k>=key[x]);
}
}
int erase(int &x,int k) {
--size[x];
if(key[x]==k||(k<key[x]&&ch[x][0]==0)||(k>key[x]&&ch[x][1]==0)) {
int ret=key[x];
if(ch[x][0]&&ch[x][1])
key[x]=erase(ch[x][0],key[x]+1);
else
x=ch[x][0]+ch[x][1];
} else
return erase(ch[x][k>=key[x]],k);
}
void insert(int k,int v) {
insert(root,k,v);
}
void erase(int k) {
erase(root,k);
}
int getMin(int x) {
while(ch[x][0])
x=ch[x][0];
return x;
}
int getMax(int x) {
while(ch[x][1])
x=ch[x][1];
return x;
}
int getLow() {
if(size[root]==0)
return 0;
int x=getMin(root),ret=val[x];
erase(key[x]);
return ret;
}
int getHigh() {
if(size[root]==0)
return 0;
int x=getMax(root),ret=val[x];
erase(key[x]);
return ret;
}
} sbt;
int main() {
int op,k,p;
while(~scanf("%d",&op)&&op)
switch(op) {
case 1:
scanf("%d%d",&k,&p);
sbt.insert(p,k);
break;
case 2:
printf("%d\n",sbt.getHigh());
break;
case 3:
printf("%d\n",sbt.getLow());
break;
}
}
#include<cstdio>
#include<cstdlib>
using namespace std;
const int MAX_LEVEL=18;
struct SkipList {
struct node {
int key,val;
node *next[1];
};
int level;
node *head;
SkipList() {
level=0;
head=newNode(MAX_LEVEL-1,0,0);
for(int i=0; i<MAX_LEVEL; ++i)
head->next[i]=NULL;
}
node* newNode(int level,int key,int val) {
node *ns=(node *)malloc(sizeof(node)+level*sizeof(node*));
ns->key=key;
ns->val=val;
return ns;
}
int randomLevel() {
int k=1;
while(rand()&1)
++k;
return k<MAX_LEVEL?k:MAX_LEVEL;
}
bool insert(int key,int val) {
node *update[MAX_LEVEL],*p=head,*q=NULL;
for(int i=level-1; i>=0; --i) {
while((q=p->next[i])&&q->key<key)
p=q;
update[i]=p;
}
if(q&&q->key==key)
return false;
int k=randomLevel();
if(k>level) {
for(int i=level; i<k; ++i)
update[i]=head;
level=k;
}
q=newNode(k,key,val);
for(int i=0; i<k; ++i) {
q->next[i]=update[i]->next[i];
update[i]->next[i]=q;
}
return true;
}
bool erase(int key) {
node *update[MAX_LEVEL],*p=head,*q=NULL;
for(int i=level-1; i>=0; --i) {
while((q=p->next[i])&&q->key<key)
p=q;
update[i]=p;
}
if(q&&q->key==key) {
for(int i=0; i<level; ++i)
if(update[i]->next[i]==q)
update[i]->next[i]=q->next[i];
free(q);
for(int i=level-1; i>=0; --i)
if(!head->next[i])
--level;
return true;
}
return false;
}
int getLow() {
node *p=head->next[0];
if(!p)
return 0;
int ret=p->val;
erase(p->key);
return ret;
}
int getHigh() {
node *p=head,*q=NULL;
for(int i=level-1; i>=0; --i)
while((q=p->next[i])&&q)
p=q;
if(p==head)
return 0;
int ret=p->val;
erase(p->key);
return ret;
}
} sl;
int main() {
int op,k,p;
while(~scanf("%d",&op)&&op)
switch(op) {
case 1:
scanf("%d%d",&k,&p);
sl.insert(p,k);
break;
case 2:
printf("%d\n",sl.getHigh());
break;
case 3:
printf("%d\n",sl.getLow());
break;
}
}
POJ1442
难度一颗星;平衡树插入、求第k小。Treap、Size Balanced Tree各一发。
#include<cstdio>
#include<cstdlib>
using namespace std;
const int MAXN=30005;
const int INF=0x3f3f3f3f;
struct Treap {
int tot,root;
int ch[MAXN][2],key[MAXN],pt[MAXN],size[MAXN];
Treap() {
tot=1;
root=0;
pt[0]=INF;
size[0]=0;
}
void rotate(int &x,int t) {
int y=ch[x][t];
ch[x][t]=ch[y][t^1];
ch[y][t^1]=x;
size[y]=size[x];
size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
x=y;
}
bool insert(int &x,int k) {
if(!x) {
x=tot++;
ch[x][0]=ch[x][1]=0;
key[x]=k;
pt[x]=rand();
size[x]=1;
} else {
int t=key[x]<k;
++size[x];
insert(ch[x][t],k);
if(pt[ch[x][t]]<pt[x])
rotate(x,t);
}
}
void insert(int k) {
insert(root,k);
}
int getKth(int k) {
int x=root;
while(size[ch[x][0]]+1!=k)
if(k<size[ch[x][0]]+1)
x=ch[x][0];
else {
k-=size[ch[x][0]]+1;
x=ch[x][1];
}
return key[x];
}
};
int a[MAXN],u[MAXN];
int main() {
int m,n;
while(~scanf("%d%d",&m,&n)) {
Treap treap;
for(int i=1; i<=m; ++i)
scanf("%d",&a[i]);
for(int i=0; i<n; ++i)
scanf("%d",&u[i]);
int pos=0;
for(int i=1; i<=m; ++i) {
treap.insert(a[i]);
while(i==u[pos])
printf("%d\n",treap.getKth(++pos));
}
}
}
#include<cstdio>
using namespace std;
const int MAXN=30005;
struct SBT {
int root,tot;
int ch[MAXN][2],key[MAXN],size[MAXN];
SBT() {
tot=1;
root=0;
size[0]=0;
}
void rotate(int &x,int t) {
int y=ch[x][t];
ch[x][t]=ch[y][t^1];
ch[y][t^1]=x;
size[y]=size[x];
size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
x=y;
}
void Maintain(int &x,int t) {
if(size[ch[ch[x][t]][t]]>size[ch[x][t^1]])
rotate(x,t);
else if(size[ch[ch[x][t]][t^1]]>size[ch[x][t^1]]) {
rotate(ch[x][t],t^1);
rotate(x,t);
}
else
return;
Maintain(ch[x][0],0);
Maintain(ch[x][1],1);
Maintain(x,0);
Maintain(x,1);
}
void insert(int &x,int k) {
if(!x) {
x=tot++;
ch[x][0]=ch[x][1]=0;
key[x]=k;
size[x]=1;
} else {
++size[x];
insert(ch[x][key[x]<k],k);
Maintain(x,key[x]<k);
}
}
void insert(int k) {
insert(root,k);
}
int getKth(int k) {
int x=root;
while(size[ch[x][0]]+1!=k)
if(k<size[ch[x][0]]+1)
x=ch[x][0];
else {
k-=size[ch[x][0]]+1;
x=ch[x][1];
}
return key[x];
}
};
int a[MAXN],u[MAXN];
int main() {
int m,n;
while(~scanf("%d%d",&m,&n)) {
SBT sbt;
for(int i=1; i<=m; ++i)
scanf("%d",&a[i]);
for(int i=0; i<n; ++i)
scanf("%d",&u[i]);
int pos=0;
for(int i=1; i<=m; ++i) {
sbt.insert(a[i]);
while(i==u[pos])
printf("%d\n",sbt.getKth(++pos));
}
}
}
SPOJ3273
难度一星半;平衡树插入、删除、求第k小,求排名。Treap、两种姿势Size Balanced Tree各一发。
#include<cstdio>
#include<cstdlib>
using namespace std;
const int MAXN=200005;
const int INF=0x3f3f3f3f;
struct Treap {
int tot,root;
int ch[MAXN][2],key[MAXN],pt[MAXN],size[MAXN];
Treap() {
tot=1;
root=0;
pt[0]=INF;
size[0]=0;
}
void rotate(int &x,int t) {
int y=ch[x][t];
ch[x][t]=ch[y][t^1];
ch[y][t^1]=x;
size[y]=size[x];
size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
x=y;
}
bool insert(int &x,int k) {
if(!x) {
x=tot++;
ch[x][0]=ch[x][1]=0;
key[x]=k;
pt[x]=rand();
size[x]=1;
return true;
}
if(key[x]==k)
return false;
int t=key[x]<k;
if(!insert(ch[x][t],k))
return false;
++size[x];
if(pt[ch[x][t]]<pt[x])
rotate(x,t);
return true;
}
bool remove(int &x,int k) {
if(!x)
return false;
if(key[x]!=k) {
if(!remove(ch[x][key[x]<k],k))
return false;
--size[x];
} else if(!ch[x][0]&&!ch[x][1])
x=0;
else if(!ch[x][0])
x=ch[x][1];
else if(!ch[x][1])
x=ch[x][0];
else {
rotate(x,pt[ch[x][0]]>pt[ch[x][1]]);
if(!remove(ch[x][key[x]<k],k))
return false;
--size[x];
}
return true;
}
void insert(int k) {
insert(root,k);
}
void remove(int k) {
remove(root,k);
}
int getKth(int k) {
int x=root;
while(size[ch[x][0]]+1!=k)
if(k<size[ch[x][0]]+1)
x=ch[x][0];
else {
k-=size[ch[x][0]]+1;
x=ch[x][1];
}
return key[x];
}
int getRank(int k) {
int ret=0,x=root;
while(x)
if(k<key[x])
x=ch[x][0];
else {
ret+=size[ch[x][0]]+1;
x=ch[x][1];
}
return ret;
}
} treap;
int main() {
int n,num;
char c;
scanf("%d",&n);
while(n--) {
scanf(" %c%d",&c,&num);
switch(c) {
case 'I':
treap.insert(num);
break;
case 'D':
treap.remove(num);
break;
case 'K':
num<=treap.size[treap.root]?printf("%d\n",treap.getKth(num)):puts("invalid");
break;
case 'C':
printf("%d\n",treap.getRank(num-1));
break;
}
}
}
#include<cstdio>
using namespace std;
const int MAXN=200005;
struct SBT {
int root,tot;
int ch[MAXN][2],key[MAXN],size[MAXN];
SBT() {
tot=1;
root=0;
size[0]=0;
}
void rotate(int &x,int t) {
int y=ch[x][t];
ch[x][t]=ch[y][t^1];
ch[y][t^1]=x;
size[y]=size[x];
size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
x=y;
}
void Maintain(int &x,int t) {
if(size[ch[ch[x][t]][t]]>size[ch[x][t^1]])
rotate(x,t);
else if(size[ch[ch[x][t]][t^1]]>size[ch[x][t^1]]) {
rotate(ch[x][t],t^1);
rotate(x,t);
} else
return;
Maintain(ch[x][0],0);
Maintain(ch[x][1],1);
Maintain(x,0);
Maintain(x,1);
}
bool insert(int &x,int k) {
if(!x) {
x=tot++;
ch[x][0]=ch[x][1]=0;
key[x]=k;
size[x]=1;
return true;
}
if(key[x]==k)
return false;
int t=k>=key[x];
if(!insert(ch[x][t],k))
return false;
++size[x];
Maintain(x,t);
return true;
}
bool remove(int &x,int k) {
if(!x)
return false;
int t;
if(key[x]==k) {
if(!ch[x][1]) {
x=ch[x][0];
return true;
}
if(!ch[x][0]) {
x=ch[x][1];
return true;
}
int r=ch[x][1];
while(ch[r][0])
r=ch[r][0];
key[x]=key[r];
remove(ch[x][1],key[r]);
t=0;
} else {
t=k<key[x];
remove(ch[x][t^1],k);
}
Maintain(x,t);
size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
return true;
}
void insert(int k) {
insert(root,k);
}
void remove(int k) {
remove(root,k);
}
int getKth(int k) {
int x=root;
while(size[ch[x][0]]+1!=k)
if(k<size[ch[x][0]]+1)
x=ch[x][0];
else {
k-=size[ch[x][0]]+1;
x=ch[x][1];
}
return key[x];
}
int getRank(int k) {
int ret=0,x=root;
while(x)
if(k<key[x])
x=ch[x][0];
else {
ret+=size[ch[x][0]]+1;
x=ch[x][1];
}
return ret;
}
} sbt;
int main() {
int n,num;
char c;
scanf("%d",&n);
while(n--) {
scanf(" %c%d",&c,&num);
switch(c) {
case 'I':
sbt.insert(num);
break;
case 'D':
sbt.remove(num);
break;
case 'K':
num<=sbt.size[sbt.root]?printf("%d\n",sbt.getKth(num)):puts("invalid");
break;
case 'C':
printf("%d\n",sbt.getRank(num-1));
break;
}
}
}
#include<cstdio>
using namespace std;
const int MAXN=200005;
struct SBT {
int root,tot;
int ch[MAXN][2],key[MAXN],size[MAXN];
SBT() {
tot=1;
root=0;
size[0]=0;
}
void rotate(int &x,int t) {
int y=ch[x][t];
ch[x][t]=ch[y][t^1];
ch[y][t^1]=x;
size[y]=size[x];
size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
x=y;
}
void Maintain(int &x,int t) {
if(size[ch[ch[x][t]][t]]>size[ch[x][t^1]])
rotate(x,t);
else if(size[ch[ch[x][t]][t^1]]>size[ch[x][t^1]]) {
rotate(ch[x][t],t^1);
rotate(x,t);
} else
return;
Maintain(ch[x][0],0);
Maintain(ch[x][1],1);
Maintain(x,0);
Maintain(x,1);
}
void insert(int &x,int k) {
if(!x) {
x=tot++;
ch[x][0]=ch[x][1]=0;
key[x]=k;
size[x]=1;
} else {
++size[x];
insert(ch[x][key[x]<k],k);
Maintain(x,key[x]<k);
}
}
int remove(int &x,int k) {
--size[x];
if(key[x]==k||(key[x]>k&&ch[x][0]==0)||(key[x]<k&&ch[x][1]==0)) {
int ret=key[x];
if(ch[x][0]&&ch[x][1])
key[x]=remove(ch[x][0],key[x]+1);
else
x=ch[x][0]+ch[x][1];
return ret;
}
return remove(ch[x][key[x]<k],k);
}
bool find(int x,int k) {
while(x) {
if(key[x]==k)
return true;
x=ch[x][key[x]<k];
}
return false;
}
void insert(int k) {
if(!find(root,k))
insert(root,k);
}
void remove(int k) {
if(find(root,k))
remove(root,k);
}
int getKth(int k) {
int x=root;
while(size[ch[x][0]]+1!=k)
if(k<size[ch[x][0]]+1)
x=ch[x][0];
else {
k-=size[ch[x][0]]+1;
x=ch[x][1];
}
return key[x];
}
int getRank(int k) {
int ret=0,x=root;
while(x)
if(k<key[x])
x=ch[x][0];
else {
ret+=size[ch[x][0]]+1;
x=ch[x][1];
}
return ret;
}
} sbt;
int main() {
int n,num;
char c;
scanf("%d",&n);
while(n--) {
scanf(" %c%d",&c,&num);
switch(c) {
case 'I':
sbt.insert(num);
break;
case 'D':
sbt.remove(num);
break;
case 'K':
num<=sbt.size[sbt.root]?printf("%d\n",sbt.getKth(num)):puts("invalid");
break;
case 'C':
printf("%d\n",sbt.getRank(num-1));
break;
}
}
}
BZOJ1588
难度一颗星;平衡树插入、求前驱、求后继。两种姿势Treap、两种姿势Size Balanced Tree各一发。
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN=40005;
const int INF=0x3f3f3f3f;
struct Treap {
int tot,root;
int ch[MAXN][2],key[MAXN],pt[MAXN],cnt[MAXN],size[MAXN];
Treap() {
tot=root=0;
pt[0]=INF;
size[0]=0;
}
void update(int x) {
size[x]=size[ch[x][0]]+cnt[x]+size[ch[x][1]];
}
void rotate(int &x,int t) {
int y=ch[x][t];
ch[x][t]=ch[y][t^1];
ch[y][t^1]=x;
update(x);
update(y);
x=y;
}
void insert(int &x,int k) {
if(x) {
if(key[x]==k)
++cnt[x];
else {
int t=key[x]<k;
insert(ch[x][t],k);
if(pt[ch[x][t]]<pt[x])
rotate(x,t);
}
} else {
x=++tot;
ch[x][0]=ch[x][1]=0;
key[x]=k;
pt[x]=rand();
cnt[x]=1;
}
update(x);
}
void insert(int k) {
insert(root,k);
}
int getPre(int x,int y,int k) {
if(x==0)
return y;
if(k==key[x]&&cnt[x]>1)
return x;
if(k>key[x])
return getPre(ch[x][1],x,k);
else
return getPre(ch[x][0],y,k);
}
int getNext(int x,int y,int k) {
if(x==0)
return y;
if(k==key[x]&&cnt[x]>1)
return x;
if(k<key[x])
getNext(ch[x][0],x,k);
else
getNext(ch[x][1],y,k);
}
int getPre(int k) {
return getPre(root,0,k);
}
int getNext(int k) {
return getNext(root,0,k);
}
int sigma(int k) {
int pre=getPre(k),next=getNext(k),ret=INF;
if(pre)
ret=min(ret,k-key[pre]);
if(next)
ret=min(ret,key[next]-k);
return ret==INF?k:ret;
}
};
int main() {
int n,x;
while(~scanf("%d",&n)) {
Treap treap;
int ans=0;
while(n--) {
if(!~scanf("%d",&x))
x=0;
treap.insert(x);
ans+=treap.sigma(x);
}
printf("%d\n",ans);
}
}
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN=40005;
const int INF=0x3f3f3f3f;
struct Treap {
int tot,root;
int ch[MAXN][2],key[MAXN],pt[MAXN],size[MAXN];
Treap() {
tot=root=0;
pt[0]=INF;
size[0]=0;
}
void rotate(int &x,int t) {
int y=ch[x][t];
ch[x][t]=ch[y][t^1];
ch[y][t^1]=x;
size[y]=size[x];
size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
x=y;
}
bool insert(int &x,int k) {
if(!x) {
x=++tot;
ch[x][0]=ch[x][1]=0;
key[x]=k;
pt[x]=rand();
size[x]=1;
return true;
}
if(key[x]==k)
return false;
int t=key[x]<k;
if(!insert(ch[x][t],k))
return false;
++size[x];
if(pt[ch[x][t]]<pt[x])
rotate(x,t);
return true;
}
bool insert(int k) {
return insert(root,k);
}
int getPre(int x,int y,int k) {
if(x==0)
return y;
if(k>key[x])
return getPre(ch[x][1],x,k);
else
return getPre(ch[x][0],y,k);
}
int getNext(int x,int y,int k) {
if(x==0)
return y;
if(k<key[x])
return getNext(ch[x][0],x,k);
else
return getNext(ch[x][1],y,k);
}
int getPre(int k) {
return getPre(root,0,k);
}
int getNext(int k) {
return getNext(root,0,k);
}
int sigma(int k) {
int pre=getPre(k),next=getNext(k),ret=INF;
if(pre)
ret=min(ret,k-key[pre]);
if(next)
ret=min(ret,key[next]-k);
return ret==INF?k:ret;
}
};
int main() {
int n,x;
while(~scanf("%d",&n)) {
Treap treap;
int ans=0;
while(n--) {
if(!~scanf("%d",&x))
x=0;
bool flag=treap.insert(x);
ans+=flag?treap.sigma(x):0;
}
printf("%d\n",ans);
}
}
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN=40005;
const int INF=0x3f3f3f3f;
struct SBT {
int root,tot;
int ch[MAXN][2],key[MAXN],size[MAXN];
SBT() {
tot=root=0;
size[0]=0;
}
void rotate(int &x,int t) {
int y=ch[x][t];
ch[x][t]=ch[y][t^1];
ch[y][t^1]=x;
size[y]=size[x];
size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
x=y;
}
void Maintain(int &x,int t) {
if(size[ch[ch[x][t]][t]]>size[ch[x][t^1]])
rotate(x,t);
else if(size[ch[ch[x][t]][t^1]]>size[ch[x][t^1]]) {
rotate(ch[x][t],t^1);
rotate(x,t);
} else
return;
Maintain(ch[x][0],0);
Maintain(ch[x][1],1);
Maintain(x,0);
Maintain(x,1);
}
void insert(int &x,int k) {
if(!x) {
x=++tot;
ch[x][0]=ch[x][1]=0;
key[x]=k;
size[x]=1;
} else {
++size[x];
insert(ch[x][key[x]<k],k);
Maintain(x,key[x]<k);
}
}
bool find(int &x,int k) {
if(!x)
return false;
if(key[x]==k)
return true;
return find(ch[x][key[x]<k],k);
}
int insert(int k) {
bool flag=find(root,k);
if(!flag)
insert(root,k);
return !flag;
}
int getPre(int x,int y,int k) {
if(x==0)
return y;
if(k>key[x])
return getPre(ch[x][1],x,k);
else
return getPre(ch[x][0],y,k);
}
int getNext(int x,int y,int k) {
if(x==0)
return y;
if(k<key[x])
return getNext(ch[x][0],x,k);
else
return getNext(ch[x][1],y,k);
}
int getPre(int k) {
return getPre(root,0,k);
}
int getNext(int k) {
return getNext(root,0,k);
}
int sigma(int k) {
int pre=getPre(k),next=getNext(k),ret=INF;
if(pre)
ret=min(ret,k-key[pre]);
if(next)
ret=min(ret,key[next]-k);
return ret==INF?k:ret;
}
};
int main() {
int n,x;
while(~scanf("%d",&n)) {
SBT sbt;
int ans=0;
while(n--) {
if(!~scanf("%d",&x))
x=0;
bool flag=sbt.insert(x);
ans+=flag?sbt.sigma(x):0;
}
printf("%d\n",ans);
}
}
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN=40005;
const int INF=0x3f3f3f3f;
struct SBT {
int root,tot;
int ch[MAXN][2],key[MAXN],size[MAXN];
SBT() {
tot=root=0;
size[0]=0;
}
void rotate(int &x,int t) {
int y=ch[x][t];
ch[x][t]=ch[y][t^1];
ch[y][t^1]=x;
size[y]=size[x];
size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
x=y;
}
void Maintain(int &x,int t) {
if(size[ch[ch[x][t]][t]]>size[ch[x][t^1]])
rotate(x,t);
else if(size[ch[ch[x][t]][t^1]]>size[ch[x][t^1]]) {
rotate(ch[x][t],t^1);
rotate(x,t);
} else
return;
Maintain(ch[x][0],0);
Maintain(ch[x][1],1);
Maintain(x,0);
Maintain(x,1);
}
bool insert(int &x,int k) {
if(!x) {
x=++tot;
ch[x][0]=ch[x][1]=0;
key[x]=k;
size[x]=1;
return true;
}
if(key[x]==k)
return false;
int t=key[x]<k;
if(!insert(ch[x][t],k))
return false;
++size[x];
Maintain(x,t);
return true;
}
bool insert(int k) {
return insert(root,k);
}
int getPre(int x,int y,int k) {
if(x==0)
return y;
if(k>key[x])
return getPre(ch[x][1],x,k);
else
return getPre(ch[x][0],y,k);
}
int getNext(int x,int y,int k) {
if(x==0)
return y;
if(k<key[x])
return getNext(ch[x][0],x,k);
else
return getNext(ch[x][1],y,k);
}
int getPre(int k) {
return getPre(root,0,k);
}
int getNext(int k) {
return getNext(root,0,k);
}
int sigma(int k) {
int pre=getPre(k),next=getNext(k),ret=INF;
if(pre)
ret=min(ret,k-key[pre]);
if(next)
ret=min(ret,key[next]-k);
return ret==INF?k:ret;
}
};
int main() {
int n,x;
while(~scanf("%d",&n)) {
SBT sbt;
int ans=0;
while(n--) {
if(!~scanf("%d",&x))
x=0;
bool flag=sbt.insert(x);
ans+=flag?sbt.sigma(x):0;
}
printf("%d\n",ans);
}
}
BZOJ1208
难度一星半;平衡树插入、删除、求前驱、求后继。两种姿势Treap、两种姿势Size Balanced Tree各一发。
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN=80005;
const int INF=0x7fffffff;
const int MOD=1000000;
struct Treap {
int tot,root;
int ch[MAXN][2],key[MAXN],pt[MAXN],cnt[MAXN],size[MAXN];
Treap() {
tot=root=0;
pt[0]=INF;
size[0]=0;
}
void update(int x) {
size[x]=size[ch[x][0]]+cnt[x]+size[ch[x][1]];
}
void rotate(int &x,int t) {
int y=ch[x][t];
ch[x][t]=ch[y][t^1];
ch[y][t^1]=x;
update(x);
update(y);
x=y;
}
void insert(int &x,int k) {
if(x) {
if(key[x]==k)
++cnt[x];
else {
int t=key[x]<k;
insert(ch[x][t],k);
if(pt[ch[x][t]]<pt[x])
rotate(x,t);
}
} else {
x=++tot;
ch[x][0]=ch[x][1]=0;
key[x]=k;
pt[x]=rand();
cnt[x]=1;
}
update(x);
}
void erase(int &x,int k) {
if(key[x]==k) {
if(cnt[x]>1)
--cnt[x];
else {
if(!ch[x][0]&&!ch[x][1]) {
x=0;
return;
}
rotate(x,pt[ch[x][0]]>pt[ch[x][1]]);
erase(x,k);
}
} else
erase(ch[x][key[x]<k],k);
update(x);
}
int getPre(int x,int y,int k) {
if(x==0)
return y;
if(k>key[x])
return getPre(ch[x][1],x,k);
else
return getPre(ch[x][0],y,k);
}
int getNext(int x,int y,int k) {
if(x==0)
return y;
if(k<key[x])
return getNext(ch[x][0],x,k);
else
return getNext(ch[x][1],y,k);
}
void insert(int k) {
insert(root,k);
}
void erase(int k) {
erase(root,k);
}
int getPre(int k) {
return getPre(root,0,k);
}
int getNext(int k) {
return getNext(root,0,k);
}
};
int main() {
int n,a,b;
while(~scanf("%d",&n)) {
Treap treap;
int ans=0,status;
while(n--) {
scanf("%d%d",&a,&b);
if(treap.size[treap.root]==0)
status=a;
treap.insert(b);
if(status!=a) {
int pre=treap.getPre(b),next=treap.getNext(b),pv=INF,nv=INF;
if(pre)
pv=b-treap.key[pre];
if(next)
nv=treap.key[next]-b;
ans+=min(pv,nv);
ans%=MOD;
if(pv<=nv)
treap.erase(treap.key[pre]);
else
treap.erase(treap.key[next]);
treap.erase(b);
}
}
printf("%d\n",ans);
}
}
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN=80005;
const int INF=0x7fffffff;
const int MOD=1000000;
struct Treap {
int tot,root;
int ch[MAXN][2],key[MAXN],pt[MAXN],size[MAXN];
Treap() {
tot=root=0;
pt[0]=INF;
size[0]=0;
}
void rotate(int &x,int t) {
int y=ch[x][t];
ch[x][t]=ch[y][t^1];
ch[y][t^1]=x;
size[y]=size[x];
size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
x=y;
}
bool insert(int &x,int k) {
if(!x) {
x=++tot;
ch[x][0]=ch[x][1]=0;
key[x]=k;
pt[x]=rand();
size[x]=1;
return true;
}
if(key[x]==k)
return false;
int t=key[x]<k;
if(!insert(ch[x][t],k))
return false;
++size[x];
if(pt[ch[x][t]]<pt[x])
rotate(x,t);
return true;
}
bool erase(int &x,int k) {
if(!x)
return false;
if(key[x]!=k) {
if(!erase(ch[x][key[x]<k],k))
return false;
--size[x];
} else if(!ch[x][0]&&!ch[x][1])
x=0;
else if(!ch[x][0])
x=ch[x][1];
else if(!ch[x][1])
x=ch[x][0];
else {
rotate(x,pt[ch[x][0]]>pt[ch[x][1]]);
if(!erase(ch[x][key[x]<k],k))
return false;
--size[x];
}
return true;
}
int getPre(int x,int y,int k) {
if(x==0)
return y;
if(k>key[x])
return getPre(ch[x][1],x,k);
else
return getPre(ch[x][0],y,k);
}
int getNext(int x,int y,int k) {
if(x==0)
return y;
if(k<key[x])
return getNext(ch[x][0],x,k);
else
return getNext(ch[x][1],y,k);
}
void insert(int k) {
insert(root,k);
}
void erase(int k) {
erase(root,k);
}
int getPre(int k) {
return getPre(root,0,k);
}
int getNext(int k) {
return getNext(root,0,k);
}
};
int main() {
int n,a,b;
while(~scanf("%d",&n)) {
Treap treap;
int ans=0,status;
while(n--) {
scanf("%d%d",&a,&b);
if(treap.size[treap.root]==0)
status=a;
treap.insert(b);
if(status!=a) {
int pre=treap.getPre(b),next=treap.getNext(b),pv=INF,nv=INF;
if(pre)
pv=b-treap.key[pre];
if(next)
nv=treap.key[next]-b;
ans+=min(pv,nv);
ans%=MOD;
if(pv<=nv)
treap.erase(treap.key[pre]);
else
treap.erase(treap.key[next]);
treap.erase(b);
}
}
printf("%d\n",ans);
}
}
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN=80005;
const int INF=0x7fffffff;
const int MOD=1000000;
struct SBT {
int root,tot;
int ch[MAXN][2],key[MAXN],size[MAXN];
SBT() {
tot=root=0;
size[0]=0;
}
void rotate(int &x,int t) {
int y=ch[x][t];
ch[x][t]=ch[y][t^1];
ch[y][t^1]=x;
size[y]=size[x];
size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
x=y;
}
void Maintain(int &x,int t) {
if(size[ch[ch[x][t]][t]]>size[ch[x][t^1]])
rotate(x,t);
else if(size[ch[ch[x][t]][t^1]]>size[ch[x][t^1]]) {
rotate(ch[x][t],t^1);
rotate(x,t);
} else
return;
Maintain(ch[x][0],0);
Maintain(ch[x][1],1);
Maintain(x,0);
Maintain(x,1);
}
void insert(int &x,int k) {
if(!x) {
x=++tot;
ch[x][0]=ch[x][1]=0;
key[x]=k;
size[x]=1;
} else {
++size[x];
insert(ch[x][key[x]<k],k);
Maintain(x,key[x]<k);
}
}
int erase(int &x,int k) {
--size[x];
if(key[x]==k||(key[x]>k&&ch[x][0]==0)||(key[x]<k&&ch[x][1]==0)) {
int ret=key[x];
if(ch[x][0]&&ch[x][1])
key[x]=erase(ch[x][0],key[x]+1);
else
x=ch[x][0]+ch[x][1];
return ret;
}
return erase(ch[x][key[x]<k],k);
}
int getPre(int x,int y,int k) {
if(x==0)
return y;
if(k>key[x])
return getPre(ch[x][1],x,k);
else
return getPre(ch[x][0],y,k);
}
int getNext(int x,int y,int k) {
if(x==0)
return y;
if(k<key[x])
return getNext(ch[x][0],x,k);
else
return getNext(ch[x][1],y,k);
}
void insert(int k) {
insert(root,k);
}
void erase(int k) {
erase(root,k);
}
int getPre(int k) {
return getPre(root,0,k);
}
int getNext(int k) {
return getNext(root,0,k);
}
};
int main() {
int n,a,b;
while(~scanf("%d",&n)) {
SBT sbt;
int ans=0,status;
while(n--) {
scanf("%d%d",&a,&b);
if(sbt.size[sbt.root]==0)
status=a;
sbt.insert(b);
if(status!=a) {
int pre=sbt.getPre(b),next=sbt.getNext(b),pv=INF,nv=INF;
if(pre)
pv=b-sbt.key[pre];
if(next)
nv=sbt.key[next]-b;
ans+=min(pv,nv);
ans%=MOD;
if(pv<=nv)
sbt.erase(sbt.key[pre]);
else
sbt.erase(sbt.key[next]);
sbt.erase(b);
}
}
printf("%d\n",ans);
}
}
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN=80005;
const int INF=0x7fffffff;
const int MOD=1000000;
struct SBT {
int root,tot;
int ch[MAXN][2],key[MAXN],size[MAXN];
SBT() {
tot=root=0;
size[0]=0;
}
void rotate(int &x,int t) {
int y=ch[x][t];
ch[x][t]=ch[y][t^1];
ch[y][t^1]=x;
size[y]=size[x];
size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
x=y;
}
void Maintain(int &x,int t) {
if(size[ch[ch[x][t]][t]]>size[ch[x][t^1]])
rotate(x,t);
else if(size[ch[ch[x][t]][t^1]]>size[ch[x][t^1]]) {
rotate(ch[x][t],t^1);
rotate(x,t);
} else
return;
Maintain(ch[x][0],0);
Maintain(ch[x][1],1);
Maintain(x,0);
Maintain(x,1);
}
bool insert(int &x,int k) {
if(!x) {
x=++tot;
ch[x][0]=ch[x][1]=0;
key[x]=k;
size[x]=1;
return true;
}
if(key[x]==k)
return false;
int t=key[x]<k;
if(!insert(ch[x][t],k))
return false;
++size[x];
Maintain(x,t);
return true;
}
bool erase(int &x,int k) {
if(!x)
return false;
int t;
if(key[x]==k) {
if(!ch[x][1]) {
x=ch[x][0];
return true;
}
if(!ch[x][0]) {
x=ch[x][1];
return true;
}
int r=ch[x][1];
while(ch[r][0])
r=ch[r][0];
key[x]=key[r];
erase(ch[x][1],key[r]);
t=0;
} else {
t=k<key[x];
erase(ch[x][t^1],k);
}
Maintain(x,t);
size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
return true;
}
int getPre(int x,int y,int k) {
if(x==0)
return y;
if(k>key[x])
return getPre(ch[x][1],x,k);
else
return getPre(ch[x][0],y,k);
}
int getNext(int x,int y,int k) {
if(x==0)
return y;
if(k<key[x])
return getNext(ch[x][0],x,k);
else
return getNext(ch[x][1],y,k);
}
void insert(int k) {
insert(root,k);
}
void erase(int k) {
erase(root,k);
}
int getPre(int k) {
return getPre(root,0,k);
}
int getNext(int k) {
return getNext(root,0,k);
}
};
int main() {
int n,a,b;
while(~scanf("%d",&n)) {
SBT sbt;
int ans=0,status;
while(n--) {
scanf("%d%d",&a,&b);
if(sbt.size[sbt.root]==0)
status=a;
sbt.insert(b);
if(status!=a) {
int pre=sbt.getPre(b),next=sbt.getNext(b),pv=INF,nv=INF;
if(pre)
pv=b-sbt.key[pre];
if(next)
nv=sbt.key[next]-b;
ans+=min(pv,nv);
ans%=MOD;
if(pv<=nv)
sbt.erase(sbt.key[pre]);
else
sbt.erase(sbt.key[next]);
sbt.erase(b);
}
}
printf("%d\n",ans);
}
}
HDU1890
难度两颗星;区间翻转。两种姿势Splay各一发。
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN=100005;
pair<int,int> p[MAXN];
struct Splay {
int root;
int ch[MAXN][2],pre[MAXN],size[MAXN];
void rotate(int x,int f) {
int y=pre[x];
ch[y][f^1]=ch[x][f];
pre[ch[x][f]]=y;
pre[x]=pre[y];
if(pre[x])
ch[pre[y]][ch[pre[y]][1]==y]=x;
ch[x][f]=y;
pre[y]=x;
push_up(y);
}
void splay(int x,int goal) {
push_down(x);
while(pre[x]!=goal) {
int y=pre[x],z=pre[y];
if(z==goal) {
push_down(y);
push_down(x);
rotate(x,ch[y][0]==x);
} else {
push_down(z);
push_down(y);
push_down(x);
int f=ch[z][0]==y;
if(ch[y][f]==x)
rotate(x,f^1);
else
rotate(y,f);
rotate(x,f);
}
}
push_up(x);
if(goal==0)
root=x;
}
void rotate_to(int k,int goal) {
int x=root;
push_down(x);
while(size[ch[x][0]]+1!=k) {
if(k<size[ch[x][0]]+1)
x=ch[x][0];
else {
k-=size[ch[x][0]]+1;
x=ch[x][1];
}
push_down(x);
}
splay(x,goal);
}
void NewNode(int x,int fa) {
ch[x][0]=ch[x][1]=0;
size[x]=1;
pre[x]=fa;
rev[x]=0;
}
void push_up(int x) {
size[x]=size[ch[x][0]]+1+size[ch[x][1]];
}
void push_down(int x) {
if(rev[x]) {
rev[ch[x][0]]^=1;
rev[ch[x][1]]^=1;
swap(ch[x][0],ch[x][1]);
rev[x]=0;
}
}
void build(int &x,int l,int r,int f) {
if(l>r)
return;
int m=l+r>>1;
x=m;
NewNode(x,f);
build(ch[x][0],l,m-1,x);
build(ch[x][1],m+1,r,x);
push_up(x);
}
void erase(int x) {
int y=pre[x];
if(!ch[x][0]) {
ch[y][ch[y][1]==x]=ch[x][1];
pre[ch[x][1]]=y;
} else {
int z=ch[x][0];
push_down(z);
while(ch[z][1]) {
z=ch[z][1];
push_down(z);
}
splay(z,y);
ch[z][1]=ch[x][1];
pre[ch[x][1]]=z;
ch[y][ch[y][1]==x]=z;
pre[z]=y;
}
}
void init(int n) {
root=0;
ch[0][0]=ch[0][1]=pre[0]=size[0]=0;
rev[0]=0;
build(root,1,n,0);
}
void solve(int n) {
init(n);
for(int i=1; i<=n; ++i) {
splay(p[i].second,0);
if(i>1)
putchar(' ');
printf("%d",i+size[ch[root][0]]);
rev[ch[root][0]]^=1;
erase(root);
}
putchar('\n');
}
int rev[MAXN];
} splay;
int main() {
int n;
while(~scanf("%d",&n)&&n) {
for(int i=1; i<=n; ++i) {
scanf("%d",&p[i].first);
p[i].second=i;
}
sort(p+1,p+n+1);
splay.solve(n);
}
}
#include<cstdio>
#include<algorithm>
using namespace std;
#define keyTree ch[ch[root][1]][0]
const int MAXN=100005;
pair<int,int> p[MAXN];
struct Splay {
int root;
int ch[MAXN][2],pre[MAXN],size[MAXN];
void rotate(int x,int f) {
int y=pre[x];
ch[y][f^1]=ch[x][f];
pre[ch[x][f]]=y;
pre[x]=pre[y];
if(pre[x])
ch[pre[y]][ch[pre[y]][1]==y]=x;
ch[x][f]=y;
pre[y]=x;
push_up(y);
}
void splay(int x,int goal) {
push_down(x);
while(pre[x]!=goal) {
int y=pre[x],z=pre[y];
if(z==goal) {
push_down(y);
push_down(x);
rotate(x,ch[y][0]==x);
} else {
push_down(z);
push_down(y);
push_down(x);
int f=ch[z][0]==y;
if(ch[y][f]==x)
rotate(x,f^1);
else
rotate(y,f);
rotate(x,f);
}
}
push_up(x);
if(goal==0)
root=x;
}
void rotate_to(int k,int goal) {
int x=root;
push_down(x);
while(size[ch[x][0]]+1!=k) {
if(k<size[ch[x][0]]+1)
x=ch[x][0];
else {
k-=size[ch[x][0]]+1;
x=ch[x][1];
}
push_down(x);
}
splay(x,goal);
}
void NewNode(int &x,int fa) {
ch[x][0]=ch[x][1]=0;
size[x]=1;
pre[x]=fa;
rev[x]=0;
}
void push_up(int x) {
size[x]=size[ch[x][0]]+1+size[ch[x][1]];
}
void push_down(int x) {
if(rev[x]) {
rev[ch[x][0]]^=1;
rev[ch[x][1]]^=1;
swap(ch[x][0],ch[x][1]);
rev[x]=0;
}
}
void build(int &x,int l,int r,int f) {
if(l>r)
return;
int m=l+r>>1;
x=m;
NewNode(x,f);
build(ch[x][0],l,m-1,x);
build(ch[x][1],m+1,r,x);
push_up(x);
}
void init(int n) {
ch[0][0]=ch[0][1]=size[0]=0;
rev[0]=0;
root=n+1;
NewNode(root,0);
ch[root][1]=n+2;
NewNode(ch[root][1],root);
size[root]=2;
build(keyTree,1,n,ch[root][1]);
push_up(ch[root][1]);
push_up(root);
}
int get_next(int x) {
push_down(x);
if(ch[x][1]==0)
return -1;
x=ch[x][1];
while(ch[x][0]) {
x=ch[x][0];
push_down(x);
}
return x;
}
void solve(int n) {
init(n);
for(int i=1; i<=n; ++i) {
splay(p[i].second,0);
if(i>1)
putchar(' ');
printf("%d",size[ch[root][0]]);
rotate_to(i,0);
splay(get_next(p[i].second),root);
rev[keyTree]^=1;
push_up(ch[root][1]);
push_up(root);
}
putchar('\n');
}
int rev[MAXN];
} splay;
int main() {
int n;
while(~scanf("%d",&n)&&n) {
for(int i=1; i<=n; ++i) {
scanf("%d",&p[i].first);
p[i].second=i;
}
sort(p+1,p+n+1);
splay.solve(n);
}
}
HDU3436
难度两颗星;节点移动,平衡树求第k小,求排名。Splay一发。
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN=100005;
char op[MAXN][10];
int data[MAXN],hash[MAXN],bg[MAXN<<1],ed[MAXN<<1],cnt;
int bi_search(int x) {
int l=0,r=cnt-1;
while(l<=r) {
int m=l+r>>1;
if(bg[m]<=x&&ed[m]>=x)
return m;
if(ed[m]<x)
l=m+1;
else
r=m-1;
}
}
struct SplayTree {
int root,tot;
int ch[MAXN<<1][2],pre[MAXN<<1],size[MAXN<<1];
void rotate(int x,int f) {
int y=pre[x];
ch[y][f^1]=ch[x][f];
pre[ch[x][f]]=y;
pre[x]=pre[y];
if(pre[x])
ch[pre[y]][ch[pre[y]][1]==y]=x;
ch[x][f]=y;
pre[y]=x;
push_up(y);
}
void splay(int x,int goal) {
while(pre[x]!=goal)
if(pre[pre[x]]==goal)
rotate(x,ch[pre[x]][0]==x);
else {
int y=pre[x],z=pre[y],f=ch[z][0]==y;
if(ch[y][f]==x)
rotate(x,f^1);
else
rotate(y,f);
rotate(x,f);
}
push_up(x);
if(goal==0)
root=x;
}
void rotate_to(int k,int goal) {
int x=root;
while(size[ch[x][0]]+1!=k)
if(k<size[ch[x][0]]+1)
x=ch[x][0];
else {
k-=size[ch[x][0]]+1;
x=ch[x][1];
}
splay(x,goal);
}
void NewNode(int &x,int fa,int k) {
x=++tot;
ch[x][0]=ch[x][1]=0;
size[x]=num[x]=ed[k]-bg[k]+1;
pre[x]=fa;
key[x]=k;
node[k]=x;
}
void push_up(int x) {
size[x]=size[ch[x][0]]+size[ch[x][1]]+num[x];
}
void build(int &x,int l,int r,int f) {
if(l>r)
return;
int m=l+r>>1;
NewNode(x,f,m);
build(ch[x][0],l,m-1,x);
build(ch[x][1],m+1,r,x);
push_up(x);
}
void init() {
root=tot=0;
ch[0][0]=ch[0][1]=size[0]=0;
build(root,0,cnt-1,0);
}
int get_rank(int x) {
int k=bi_search(x);
splay(node[k],0);
return size[ch[root][0]]+1;
}
int get_kth(int x,int k) {
int t=size[ch[x][0]];
if(t>=k)
return get_kth(ch[x][0],k);
else if(t+num[x]>=k)
return bg[key[x]]+k-t-1;
else
return get_kth(ch[x][1],k-t-num[x]);
}
void insert(int &x,int k,int fa) {
if(x==0) {
NewNode(x,fa,k);
splay(x,0);
return;
}
insert(ch[x][0],k,x);
push_up(x);
}
void del() {
int x=root;
if(ch[root][1]) {
root=ch[root][1];
rotate_to(1,0);
ch[root][0]=ch[x][0];
if(ch[root][0])
pre[ch[root][0]]=root;
} else
root=ch[root][0];
pre[root]=0;
push_up(root);
}
void top(int x) {
int k=bi_search(x);
splay(node[k],0);
del();
insert(root,k,0);
splay(node[k],0);
}
int key[MAXN<<1],num[MAXN<<1],node[MAXN<<1];
} splay;
int main() {
int t,n,q;
scanf("%d",&t);
for(int cas=1; cas<=t; ++cas) {
scanf("%d%d",&n,&q);
int tot=cnt=0;
hash[tot++]=0;
for(int i=0; i<q; ++i) {
scanf("%s%d",op[i],&data[i]);
if(op[i][0]!='R')
hash[tot++]=data[i];
}
hash[tot++]=n;
sort(hash,hash+tot);
tot=unique(hash,hash+tot)-hash;
for(int i=1; i<tot; ++i) {
if(hash[i]-hash[i-1]>1) {
bg[cnt]=hash[i-1]+1;
ed[cnt]=hash[i]-1;
++cnt;
}
bg[cnt]=ed[cnt]=hash[i];
++cnt;
}
printf("Case %d:\n",cas);
splay.init();
for(int i=0; i<q; ++i)
switch(op[i][0]) {
case 'T':
splay.top(data[i]);
break;
case 'Q':
printf("%d\n",splay.get_rank(data[i]));
break;
case 'R':
printf("%d\n",splay.get_kth(splay.root,data[i]));
break;
}
}
}
HDU3487
难度两星半;区间分割(移动),区间翻转。Splay一发。
#include<cstdio>
#include<algorithm>
using namespace std;
#define keyTree (ch[ch[root][1]][0])
const int MAXN=300005;
struct SplayTree {
int root,tot;
int ch[MAXN][2],pre[MAXN],size[MAXN];
void rotate(int x,int f) {
int y=pre[x];
ch[y][f^1]=ch[x][f];
pre[ch[x][f]]=y;
pre[x]=pre[y];
if(pre[x])
ch[pre[y]][ch[pre[y]][1]==y]=x;
ch[x][f]=y;
pre[y]=x;
push_up(y);
}
void splay(int x,int goal) {
push_down(x);
while(pre[x]!=goal) {
int y=pre[x],z=pre[y];
if(z==goal) {
push_down(y);
push_down(x);
rotate(x,ch[y][0]==x);
} else {
push_down(z);
push_down(y);
push_down(x);
int f=ch[z][0]==y;
if(ch[y][f]==x)
rotate(x,f^1);
else
rotate(y,f);
rotate(x,f);
}
}
push_up(x);
if(goal==0)
root=x;
}
void rotate_to(int k,int goal) {
int x=root;
push_down(x);
while(size[ch[x][0]]!=k) {
if(k<size[ch[x][0]])
x=ch[x][0];
else {
k-=size[ch[x][0]]+1;
x=ch[x][1];
}
push_down(x);
}
splay(x,goal);
}
void NewNode(int &x,int c,int fa) {
x=++tot;
ch[x][0]=ch[x][1]=0;
size[x]=1;
pre[x]=fa;
key[x]=c;
rev[x]=0;
}
void push_up(int x) {
size[x]=1+size[ch[x][0]]+size[ch[x][1]];
}
void push_down(int x) {
if(rev[x]) {
rev[ch[x][0]]^=1;
rev[ch[x][1]]^=1;
swap(ch[x][0],ch[x][1]);
rev[x]=0;
}
}
void build(int &x,int l,int r,int f) {
if(l>r)
return;
int m=l+r>>1;
NewNode(x,m,f);
build(ch[x][0],l,m-1,x);
build(ch[x][1],m+1,r,x);
push_up(x);
}
void init(int n) {
root=tot=0;
ch[0][0]=ch[0][1]=size[0]=0;
rev[0]=0;
NewNode(root,-1,0);
NewNode(ch[root][1],-1,root);
size[root]=2;
build(keyTree,1,n,ch[root][1]);
push_up(ch[root][1]);
push_up(root);
}
void reverse(int l,int r) {
rotate_to(l-1,0);
rotate_to(r+1,root);
rev[keyTree]^=1;
}
void cut(int l,int r,int p) {
rotate_to(l-1,0);
rotate_to(r+1,root);
int tmp=keyTree;
keyTree=0;
push_up(ch[root][1]);
push_up(root);
rotate_to(p,0);
rotate_to(p+1,root);
keyTree=tmp;
pre[keyTree]=ch[root][1];
push_up(ch[root][1]);
push_up(root);
}
void InOrder(int x) {
if(!x)
return;
push_down(x);
InOrder(ch[x][0]);
if(key[x]!=-1) {
if(cnt>1)
putchar(' ');
printf("%d" ,key[x]);
}
++cnt;
InOrder(ch[x][1]);
}
void output() {
cnt=0;
InOrder(root);
putchar('\n');
}
int key[MAXN],rev[MAXN],cnt;
} splay;
int main() {
int n,m,a,b,c;
char op[5];
while(~scanf("%d%d",&n,&m)&&~n&&~m) {
splay.init(n);
while(m--) {
scanf("%s%d%d",op,&a,&b);
switch(op[0]) {
case 'C':
scanf("%d",&c);
splay.cut(a,b,c);
break;
case 'F':
splay.reverse(a,b);
break;
}
}
splay.output();
}
}
ZOJ2112
难度三星半;单点修改,区间第k小。树状数组+可持久化线段树(主席树)、两种姿势线段树+Treap各一发。
#include<cstdio>
#include<algorithm>
using namespace std;
#define lson l,m,ls[rt]
#define rson m+1,r,rs[rt]
const int MAXN=60005;
const int MAXM=2500005;
int t,n,m,size;
int ls[MAXM],rs[MAXM],cnt[MAXM],root[MAXN],tot;
void build(int l,int r,int &rt) {
rt=tot++;
cnt[rt]=0;
if(l==r)
return;
int m=(l+r)>>1;
build(lson);
build(rson);
}
void update(int last,int p,int val,int l,int r,int &rt) {
rt=tot++;
ls[rt]=ls[last];
rs[rt]=rs[last];
cnt[rt]=cnt[last]+val;
if(l==r)
return;
int m=(l+r)>>1;
if(p<=m)
update(ls[last],p,val,lson);
else
update(rs[last],p,val,rson);
}
int bit[MAXN],use[MAXN];
inline int lowbit(int x) {
return x&-x;
}
void modify(int x,int p,int val) {
for(int i=x; i<=n; i+=lowbit(i))
update(bit[i],p,val,1,size,bit[i]);
}
int sum(int x) {
int ret=0;
for(int i=x; i>0; i-=lowbit(i))
ret+=cnt[ls[use[i]]];
return ret;
}
int query(int ss,int tt,int l,int r,int k) {
for(int i=ss; i>0; i-=lowbit(i))
use[i]=bit[i];
for(int i=tt; i>0; i-=lowbit(i))
use[i]=bit[i];
int sr=root[ss],tr=root[tt];
while(l<r) {
int m=(l+r)>>1,tmp=sum(tt)-sum(ss)+cnt[ls[tr]]-cnt[ls[sr]];
if(k<=tmp) {
r=m;
for(int i=ss; i>0; i-=lowbit(i))
use[i]=ls[use[i]];
for(int i=tt; i>0; i-=lowbit(i))
use[i]=ls[use[i]];
sr=ls[sr];
tr=ls[tr];
} else {
l=m+1;
k-=tmp;
for(int i=ss; i>0; i-=lowbit(i))
use[i]=rs[use[i]];
for(int i=tt; i>0; i-=lowbit(i))
use[i]=rs[use[i]];
sr=rs[sr];
tr=rs[tr];
}
}
return l;
}
int num[MAXN],hash[MAXN],l[MAXN],r[MAXN],k[MAXN];
char op[MAXN];
int main() {
scanf("%d",&t);
while(t--) {
scanf("%d%d",&n,&m);
size=0;
for(int i=1; i<=n; ++i) {
scanf("%d",&num[i]);
hash[++size]=num[i];
}
for(int i=0; i<m; ++i) {
scanf(" %c%d%d",&op[i],&l[i],&r[i]);
switch(op[i]) {
case 'Q':
scanf("%d",&k[i]);
break;
case 'C':
hash[++size]=r[i];
break;
}
}
sort(hash+1,hash+size+1);
size=unique(hash+1,hash+size+1)-hash-1;
for(int i=1; i<=n; ++i)
num[i]=lower_bound(hash+1,hash+size+1,num[i])-hash;
tot=0;
build(1,size,root[0]);
for(int i=1; i<=n; ++i)
update(root[i-1],num[i],1,1,size,root[i]);
for(int i=1; i<=n; ++i)
bit[i]=root[0];
for(int i=0; i<m; ++i)
switch(op[i]) {
case 'Q':
printf("%d\n",hash[query(l[i]-1,r[i],1,size,k[i])]);
break;
case 'C':
modify(l[i],num[l[i]],-1);
num[l[i]]=lower_bound(hash+1,hash+size+1,r[i])-hash;
modify(l[i],num[l[i]],1);
break;
}
}
}
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int MAXN=60005;
const int MAXM=900005;
const int INF=0x3f3f3f3f;
int ch[MAXM][2],key[MAXM],pt[MAXM],cnt[MAXM],size[MAXM],tot,root;
void init() {
tot=root=0;
pt[0]=-INF;
size[0]=0;
}
void update(int x) {
size[x]=size[ch[x][0]]+cnt[x]+size[ch[x][1]];
}
void rotate(int &x,int t) {
int y=ch[x][t];
ch[x][t]=ch[y][t^1];
ch[y][t^1]=x;
update(x);
update(y);
x=y;
}
void insert(int &x,int k) {
if(x) {
if(key[x]==k)
++cnt[x];
else {
int t=key[x]<k;
insert(ch[x][t],k);
if(pt[ch[x][t]]>pt[x])
rotate(x,t);
}
} else {
x=++tot;
ch[x][0]=ch[x][1]=0;
key[x]=k;
pt[x]=rand();
cnt[x]=1;
}
update(x);
}
void erase(int &x,int k) {
if(key[x]==k) {
if(cnt[x]>1)
--cnt[x];
else {
if(!ch[x][0]&&!ch[x][1]) {
x=0;
return;
}
rotate(x,pt[ch[x][0]]<pt[ch[x][1]]);
erase(x,k);
}
} else
erase(ch[x][key[x]<k],k);
update(x);
}
int seg[MAXN<<2];
int calc(int x,int k) {
if(!x)
return 0;
if(k<key[x])
return calc(ch[x][0],k);
else
return size[ch[x][0]]+cnt[x]+calc(ch[x][1],k);
}
void segins(int p,int val,int l,int r,int rt) {
insert(seg[rt],val);
if(l==r)
return;
int m=l+r>>1;
if(p<=m)
segins(p,val,lson);
else
segins(p,val,rson);
}
void segdel(int p,int val,int l,int r,int rt) {
erase(seg[rt],val);
if(l==r)
return;
int m=l+r>>1;
if(p<=m)
segdel(p,val,lson);
else
segdel(p,val,rson);
}
int query(int L,int R,int k,int l,int r,int rt) {
if(l==r)
return l;
int m=l+r>>1,cnt=calc(seg[rt<<1],R)-calc(seg[rt<<1],L);
if(k<=cnt)
return query(L,R,k,lson);
else
return query(L,R,k-cnt,rson);
}
int num[MAXN],hash[MAXN],l[MAXN],r[MAXN],k[MAXN];
char op[MAXN];
int main() {
int t,n,m;
scanf("%d",&t);
while(t--) {
scanf("%d%d",&n,&m);
int hs=0;
for(int i=1; i<=n; ++i) {
scanf("%d",&num[i]);
hash[++hs]=num[i];
}
for(int i=0; i<m; ++i) {
scanf(" %c%d%d",&op[i],&l[i],&r[i]);
switch(op[i]) {
case 'Q':
scanf("%d",&k[i]);
break;
case 'C':
hash[++hs]=r[i];
break;
}
}
sort(hash+1,hash+hs+1);
hs=unique(hash+1,hash+hs+1)-hash-1;
init();
memset(seg,0,sizeof(seg));
for(int i=1; i<=n; ++i) {
num[i]=lower_bound(hash+1,hash+hs+1,num[i])-hash;
segins(num[i],i,1,hs,1);
}
for(int i=0; i<m; ++i)
switch(op[i]) {
case 'Q':
printf("%d\n",hash[query(l[i]-1,r[i],k[i],1,hs,1)]);
break;
case 'C':
segdel(num[l[i]],l[i],1,hs,1);
num[l[i]]=lower_bound(hash+1,hash+hs+1,r[i])-hash;
segins(num[l[i]],l[i],1,hs,1);
break;
}
}
}
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int MAXN=60005;
const int MAXM=900005;
const int INF=0x3f3f3f3f;
int ch[MAXM][2],key[MAXM],pt[MAXM],size[MAXM],tot,root;
void init() {
tot=root=0;
pt[0]=INF;
size[0]=0;
}
void rotate(int &x,int t) {
int y=ch[x][t];
ch[x][t]=ch[y][t^1];
ch[y][t^1]=x;
size[y]=size[x];
size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
x=y;
}
bool insert(int &x,int k) {
if(!x) {
x=++tot;
ch[x][0]=ch[x][1]=0;
key[x]=k;
pt[x]=rand();
size[x]=1;
return true;
}
if(key[x]==k)
return false;
int t=key[x]<k;
if(!insert(ch[x][t],k))
return false;
++size[x];
if(pt[ch[x][t]]<pt[x])
rotate(x,t);
return true;
}
bool erase(int &x,int k) {
if(!x)
return false;
if(key[x]!=k) {
if(!erase(ch[x][key[x]<k],k))
return false;
--size[x];
} else if(!ch[x][0]&&!ch[x][1])
x=0;
else if(!ch[x][0])
x=ch[x][1];
else if(!ch[x][1])
x=ch[x][0];
else {
rotate(x,pt[ch[x][0]]>pt[ch[x][1]]);
if(!erase(ch[x][key[x]<k],k))
return false;
--size[x];
}
return true;
}
int seg[MAXN<<2];
int calc(int x,int k) {
if(!x)
return 0;
if(k<key[x])
return calc(ch[x][0],k);
else
return size[ch[x][0]]+1+calc(ch[x][1],k);
}
void segins(int p,int val,int l,int r,int rt) {
insert(seg[rt],val);
if(l==r)
return;
int m=l+r>>1;
if(p<=m)
segins(p,val,lson);
else
segins(p,val,rson);
}
void segdel(int p,int val,int l,int r,int rt) {
erase(seg[rt],val);
if(l==r)
return;
int m=l+r>>1;
if(p<=m)
segdel(p,val,lson);
else
segdel(p,val,rson);
}
int query(int L,int R,int k,int l,int r,int rt) {
if(l==r)
return l;
int m=l+r>>1,cnt=calc(seg[rt<<1],R)-calc(seg[rt<<1],L);
if(k<=cnt)
return query(L,R,k,lson);
else
return query(L,R,k-cnt,rson);
}
int num[MAXN],hash[MAXN],l[MAXN],r[MAXN],k[MAXN];
char op[MAXN];
int main() {
int t,n,m;
scanf("%d",&t);
while(t--) {
scanf("%d%d",&n,&m);
int hs=0;
for(int i=1; i<=n; ++i) {
scanf("%d",&num[i]);
hash[++hs]=num[i];
}
for(int i=0; i<m; ++i) {
scanf(" %c%d%d",&op[i],&l[i],&r[i]);
switch(op[i]) {
case 'Q':
scanf("%d",&k[i]);
break;
case 'C':
hash[++hs]=r[i];
break;
}
}
sort(hash+1,hash+hs+1);
hs=unique(hash+1,hash+hs+1)-hash-1;
init();
memset(seg,0,sizeof(seg));
for(int i=1; i<=n; ++i) {
num[i]=lower_bound(hash+1,hash+hs+1,num[i])-hash;
segins(num[i],i,1,hs,1);
}
for(int i=0; i<m; ++i)
switch(op[i]) {
case 'Q':
printf("%d\n",hash[query(l[i]-1,r[i],k[i],1,hs,1)]);
break;
case 'C':
segdel(num[l[i]],l[i],1,hs,1);
num[l[i]]=lower_bound(hash+1,hash+hs+1,r[i])-hash;
segins(num[l[i]],l[i],1,hs,1);
break;
}
}
}
未完待续……