昨天刷了几道QTREE,感觉码长萌萌哒;
然而因为本人太弱刷不动QTREE4,动态点分治并没有理解上去的能力;
于是暂且弃疗啦,在这里写点题解扔点代码吧;
QTREE1
题意:
给出一个有边权的树;
操作一:改变某条边权;
操作二:查询两点之间路径上最大边权;
题解:
树链剖分的姿势还是挺裸的,想了想没有什么好办法码了一发;
普通的树链剖分维护树上路径,加一个线段树,时间复杂度O(nlog^2n);
QTREE2
题意:
给出一个有边权的树;
操作一:查询两点之间路径长度;
操作二:查询两点之间路径上经过的第K个点;
题解:
因为是无修的,操作一可以方便的用倍增LCA搞;
操作二在跑过一次LCA之后,YY一下也就是从某个点向上K步之类的东西;
时间复杂度O(nlogn),手滑打错一个字母调了好久;
QTREE3
题意:
给出一个有点权的树;
每次查询某个点子树中第K小点权是哪个点;
题解:
操作只有一种,子树维护直接在DFS序上就可以了;
第K大用主席树来维护,时间复杂度O(nlogn),空间复杂度O(nlogn);
SPOJ的1.5G内存真是太爽啦 (然后到BZOJ上就MLE了);
代码:
QTREE1:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 11000
#define lson l,mid,no<<1
#define rson mid+1,r,no<<1|1
using namespace std;
int next[N<<1],to[N<<1],len[N<<1],head[N],ce;
int n,X[N],Y[N],V[N];
int val[N],deep[N],fa[N],size[N],son[N],top[N],p[N],tot;
int ma[N<<2];
char op[20];
void Pushup(int no)
{
ma[no]=max(ma[no<<1],ma[no<<1|1]);
}
void update(int l,int r,int no,int k,int val)
{
if(l==r)
ma[no]=val;
else
{
int mid=l+r>>1;
if(k<=mid) update(lson,k,val);
else update(rson,k,val);
Pushup(no);
}
}
int query(int l,int r,int no,int st,int en)
{
if(st<=l&&r<=en)
return ma[no];
else
{
int mid=l+r>>1;
if(en<=mid) return query(lson,st,en);
else if(st>mid) return query(rson,st,en);
else return max(query(lson,st,en),query(rson,st,en));
}
}
void add(int x,int y,int v)
{
to[++ce]=y;
len[ce]=v;
next[ce]=head[x];
head[x]=ce;
}
void dfs1(int x)
{
deep[x]=deep[fa[x]]+1;
size[x]=1;
for(int i=head[x];i;i=next[i])
{
if(to[i]!=fa[x])
{
fa[to[i]]=x;
val[to[i]]=len[i];
dfs1(to[i]);
size[x]+=size[to[i]];
if(size[to[i]]>size[son[x]])
son[x]=to[i];
}
}
}
void dfs2(int x,int t)
{
top[x]=t;
p[x]=++tot;
update(1,n,1,p[x],val[x]);
if(son[x])
dfs2(son[x],t);
for(int i=head[x];i;i=next[i])
if(to[i]!=fa[x]&&to[i]!=son[x])
dfs2(to[i],to[i]);
}
void init()
{
memset(head,0,sizeof(head));
memset(son,0,sizeof(son));
ce=tot=0;
}
int find(int x,int y)
{
int ret=0;
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]])
swap(x,y);
ret=max(ret,query(1,n,1,p[top[x]],p[x]));
x=fa[top[x]];
}
if(deep[x]<deep[y])
swap(x,y);
if(x!=y)
ret=max(ret,query(1,n,1,p[son[y]],p[x]));
return ret;
}
int main()
{
int c,T,i,j,k,x,y,v;
scanf("%d",&T);
for(c=1;c<=T;c++)
{
scanf("%d",&n);
init();
for(i=1;i<n;i++)
{
scanf("%d%d%d",X+i,Y+i,V+i);
add(X[i],Y[i],V[i]),add(Y[i],X[i],V[i]);
}
dfs1(1);
dfs2(1,0);
for(i=1;i<n;i++)
X[i]=deep[X[i]]>deep[Y[i]]?X[i]:Y[i];
while(scanf("%s",op)!=EOF&&op[0]!='D')
{
scanf("%d%d",&x,&y);
if(op[0]=='C')
{
val[X[x]]=y;
update(1,n,1,p[X[x]],y);
}
else
{
printf("%d\n",find(x,y));
}
}
}
return 0;
}
QTREE2:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 110000
using namespace std;
int next[N<<1],to[N<<1],val[N<<1],head[N],ce;
int fa[N][20],dis[N][20],deep[N];
char op[20];
void add(int x,int y,int v)
{
to[++ce]=y;
val[ce]=v;
next[ce]=head[x];
head[x]=ce;
}
void dfs(int x)
{
int i;
deep[x]=deep[fa[x][0]]+1;
for(i=1;fa[x][i-1];i++)
fa[x][i]=fa[fa[x][i-1]][i-1],
dis[x][i]=dis[x][i-1]+dis[fa[x][i-1]][i-1];
for(i=head[x];i;i=next[i])
{
if(to[i]!=fa[x][0])
{
fa[to[i]][0]=x;
dis[to[i]][0]=val[i];
dfs(to[i]);
}
}
}
int DIST(int x,int y)
{
if(deep[x]<deep[y])
swap(x,y);
int t=15,ret=0;
while(t>=0)
{
if(deep[fa[x][t]]>=deep[y])
ret+=dis[x][t],x=fa[x][t];
t--;
}
if(x==y) return ret;
t=15;
while(t>=0)
{
if(fa[x][t]!=fa[y][t])
ret+=dis[x][t],x=fa[x][t],
ret+=dis[y][t],y=fa[y][t];
t--;
}
return ret+dis[x][0]+dis[y][0];
}
int KTH(int x,int y,int k)
{
int t=15,retx=0,rety=0,tx=x,ty=y;
if(deep[tx]>deep[ty])
{
while(t>=0)
{
if(deep[fa[tx][t]]>=deep[ty])
retx+=(1<<t),tx=fa[tx][t];
t--;
}
}
else
{
while(t>=0)
{
if(deep[fa[ty][t]]>=deep[tx])
rety+=(1<<t),ty=fa[ty][t];
t--;
}
}
if(tx!=ty)
{
t=15;
while(t>=0)
{
if(fa[tx][t]!=fa[ty][t])
retx+=(1<<t),tx=fa[tx][t],
rety+=(1<<t),ty=fa[ty][t];
t--;
}
retx++,rety++;
}
if(retx+rety+1<k) return -1;
if(retx>=k-1)
{
k--;
t=15;
while(t>=0)
{
if(k&1<<t)
x=fa[x][t];
t--;
}
return x;
}
else
{
k=rety-k+retx+1;
t=15;
while(t>=0)
{
if(k&1<<t)
y=fa[y][t];
t--;
}
return y;
}
}
void init()
{
memset(head,0,sizeof(head));
memset(dis,0,sizeof(dis));
memset(fa,0,sizeof(fa));
ce=0;
}
int main()
{
int c,T,n,m,i,j,k,x,y,v;
scanf("%d",&T);
for(c=1;c<=T;c++)
{
init();
scanf("%d",&n);
for(i=1;i<n;i++)
{
scanf("%d%d%d",&x,&y,&v);
add(x,y,v),add(y,x,v);
}
dfs(1);
while(scanf("%s",op)!=EOF&&op[1]!='O')
{
if(op[1]=='I')
{
scanf("%d%d",&x,&y);
printf("%d\n",DIST(x,y));
}
else
{
scanf("%d%d%d",&x,&y,&k);
printf("%d\n",KTH(x,y,k));
}
}
}
return 0;
}
QTREE3:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 110000
#define M 10000000
#define lson l,mid,ls[no]
#define rson mid+1,r,rs[no]
using namespace std;
int next[N<<1],to[N<<1],head[N],ce;
int val[N],dis[N],which[N];
int n,L[N],R[N],tim;
int size[M],ls[M],rs[M],root[N],tot;
void Insert(int l,int r,int &no,int val)
{
int p=++tot;
ls[p]=ls[no],rs[p]=rs[no],size[p]=size[no];
no=p;
size[no]++;
if(l==r) return ;
int mid=l+r>>1;
if(val<=mid) Insert(lson,val);
else Insert(rson,val);
}
int query(int l,int r,int nol,int nor,int k)
{
if(l==r)
return l;
else
{
int mid=l+r>>1;
if(k<=size[ls[nor]]-size[ls[nol]])
return query(l,mid,ls[nol],ls[nor],k);
else
return query(mid+1,r,rs[nol],rs[nor],k-size[ls[nor]]+size[ls[nol]]);
}
}
void add(int x,int y)
{
to[++ce]=y;
next[ce]=head[x];
head[x]=ce;
}
void dfs(int x,int pre)
{
L[x]=++tim;
root[tim]=root[tim-1];
Insert(1,n,root[tim],val[x]);
for(int i=head[x];i;i=next[i])
if(to[i]!=pre)
dfs(to[i],x);
R[x]=tim;
}
int main()
{
int m,i,j,k,x,y;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",val+i);
dis[i]=val[i];
}
sort(dis+1,dis+n+1);
for(i=1;i<=n;i++)
{
val[i]=lower_bound(dis+1,dis+n+1,val[i])-dis;
which[val[i]]=i;
}
for(i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
add(x,y),add(y,x);
}
dfs(1,0);
scanf("%d",&m);
for(i=1;i<=m;i++)
{
scanf("%d%d",&x,&k);
printf("%d\n",which[query(1,n,root[L[x]-1],root[R[x]],k)]);
}
return 0;
}