论不会整体二分的悲伤。。代码长度感人。。然而似乎并不慢。。
看到树上路径之间的各种关系大概都会想到dfs序吧。。
然而还是看了题解= =:http://blog.csdn.net/thy_asdf/article/details/50363672
题解说得很清晰了。。就是将盘子弄成矩形,水果就看成点。询问覆盖某个点的矩形中,第k小的权值。
引用一下:“
分情况:如果u!=lca(u,v)
那么水果的两端点(a,b)就在盘子两端点的子树中
用dfs序来表示,就是dfn[u]<=a<=last[u],dfn[v]<=b<=last[v]
last[i]表示i的子树的最大 dfn
如果u==lca(u,v)
这时稍微有一些区别,w表示u的儿子且是v的祖先的点,注意不是u
那么b还是在v子树中,a在除了w子树之外的所有点中
dfn[v]<=b<=last[v],1<=a<=dfn[w]-1||last[w]+1<=a<=n ”
注:原文各不等式中的a和b应该是dfn[a]和dfn[b]....
求w的话。。首先用last值判断u是否是v的祖先。然后用链剖搞。。
注意一下,当u是v的祖先时,假如盘子(u,v)是水果(a,b)的子路径,那么有两种可能:(令dfn[u]<dfn[v],dfn[a]<dfn[b])
1、dfn[v]<=dfn[b]<=last[v],并且1<=dfn[a]<=dfn[w]-1;(路径:a->w->v->b)
2、last[w]+1<=dfn[b]<=n,并且dfn[v]<=dfn[a]<=last[v]。(路径:b->w->v->a)
实现的时候,我们可以把每个盘子,按照它的第一个不等式的左边的值升序排序一下。(dfn[v]或者last[w]+1,记为v),把水果也按dfn[b]升序排序一下。
树套树的部分,外层是1~n的区间,表示右边那个不等式(也就是第二维),内层记录对应区间内的各个权值
外层就是区间修改,单点查询了。。(我写了线段树来把修改的区间拆成logn个小区间= =。。)内层用平衡树或者线段树。。随意。
每次把符合v<=dfn[b]的盘子插进树套树里面,优先队列关键字为第一个不等式右边的值(小根堆)。。。插入完再把不符合的盘子删掉。。。(语死早TAT
这样就保证当前树套树里面的盘子都是符合第一个不等式的了。。。
时间复杂度和空间复杂度都是O(n log²n)。。。
注。。代码里面用的是size。。last[x]==dfn[x]+size[x]-1;
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<queue> 5 #include<algorithm> 6 using namespace std; 7 const int maxn=66233; 8 const int maxm=maxn*18*18; 9 struct zs{int too,pre;}e[maxn<<1]; 10 struct zs1{int id,V;}; 11 struct zs2{int a,b,K,id;}ask[maxn]; 12 struct zs3{int num,id;}A[maxn<<1]; 13 struct poi{ 14 int l1,r1,l2,r2,val; 15 }p[maxn<<1];int pnum;//盘子s 16 int last[maxn],tot; 17 int dfn[maxn],size[maxn],bel[maxn],fa[maxn],next[maxn],dep[maxn],tim; 18 int l[maxm],r[maxm],sz[maxm],tt; 19 int rt[65539<<1]; 20 int i,j,n,m,Q,x,y,a,b,nowans,zkw; 21 priority_queue<zs1>q; 22 int C[maxn],cnt; 23 int ans[maxn]; 24 25 inline void insert(int a,int b){ 26 e[++tot].too=b,e[tot].pre=last[a],last[a]=tot; 27 e[++tot].too=a,e[tot].pre=last[b],last[b]=tot; 28 } 29 void dfs1(int x){ 30 size[x]=1,dfn[x]=++tim,dep[x]=dep[fa[x]]+1; 31 for(register int i=last[x],to=e[i].too;i;to=e[i=e[i].pre].too)if(to!=fa[x]) 32 fa[to]=x,dfs1(to),size[x]+=size[to]; 33 } 34 void dfs2(int x,int chain){ 35 register int i,mx=0; 36 for(bel[x]=chain,i=last[x];i;i=e[i].pre)if(e[i].too!=fa[x]&&size[e[i].too]>=size[mx])mx=e[i].too; 37 if(!mx)return; 38 next[x]=mx,dfs2(mx,chain); 39 for(i=last[x];i;i=e[i].pre)if(e[i].too!=fa[x]&&e[i].too!=mx)dfs2(e[i].too,e[i].too); 40 } 41 int getnext(int x,int y){ 42 int pre=0; 43 while(bel[x]!=bel[y]){ 44 pre=bel[y],y=fa[bel[y]]; 45 } 46 return y==x?pre:next[x]; 47 }//-----------------------------链剖 48 49 int num[maxn],sum; 50 inline void getkth(int L,int R,int K){ 51 if(L==R){nowans=C[L];/*printf(" %d ",L);*/return;} 52 int mid=(L+R)>>1,lsz=0;register int i; 53 for(i=sum;i;i--)lsz+=sz[l[num[i]]]; 54 if(K<=lsz){ 55 for(i=sum;i;i--)num[i]=l[num[i]]; 56 getkth(L,mid,K); 57 }else{ 58 for(i=sum;i;i--)num[i]=r[num[i]]; 59 getkth(mid+1,R,K-lsz); 60 } 61 } 62 inline void ins(int &x,int L,int R,int v){ 63 if(!x)x=++tt;sz[x]++; 64 if(L==R)return;int mid=(L+R)>>1; 65 if(v<=mid)ins(l[x],L,mid,v);else ins(r[x],mid+1,R,v); 66 } 67 inline void del(int x,int L,int R,int v){ 68 sz[x]--; 69 if(L==R)return;int mid=(L+R)>>1; 70 if(v<=mid)del(l[x],L,mid,v);else del(r[x],mid+1,R,v); 71 }//-----------------------------sgt inside 72 73 inline void add(int x,int L,int R,int c,int d,int v){ 74 if(c>d)return; 75 if(c<=L&&d>=R){ins(rt[x],1,cnt,v);/*printf("add: %d--%d %d ",L,R,v);*/return;} 76 int mid=(L+R)>>1; 77 if(c<=mid)add(x<<1,L,mid,c,d,v); 78 if(d>mid) add(x<<1|1,mid+1,R,c,d,v); 79 } 80 inline void dec(int x,int L,int R,int c,int d,int v){ 81 if(c>d)return; 82 if(c<=L&&d>=R){del(rt[x],1,cnt,v);/*printf("del: %d--%d %d ",L,R,v);*/return;} 83 int mid=(L+R)>>1; 84 if(c<=mid)dec(x<<1,L,mid,c,d,v); 85 if(d>mid) dec(x<<1|1,mid+1,R,c,d,v); 86 }//-----------------------------sgt outside//可以合成一个过程然而太懒 87 88 inline void change(int id,bool ADD){ 89 int v=p[id].val,l=p[id].l2,r=p[id].r2; 90 if(ADD)add(1,1,zkw+1,l,r,v);else dec(1,1,zkw+1,l,r,v); 91 } 92 inline int kth(int dfna,int K){int tmp=0; 93 sum=0;for(int x=dfna+zkw;x;x>>=1)num[++sum]=rt[x],tmp+=sz[rt[x]]; 94 if(tmp<K)return -1; 95 getkth(1,cnt,K); 96 return nowans; 97 } 98 int ra,fh;char rx; 99 inline int read(){ 100 rx=getchar(),ra=0,fh=1; 101 while((rx<'0'||rx>'9')&&rx!='-')rx=getchar(); 102 if(rx=='-')fh=-1,rx=getchar(); 103 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra*fh; 104 } 105 bool cmp(poi a,poi b){return a.l1<b.l1;} 106 bool cmp1(zs2 x,zs2 y){return dfn[x.b]<dfn[y.b];} 107 bool cmp2(zs3 a,zs3 b){return a.num<b.num;} 108 bool operator <(zs1 a,zs1 b){return a.V>b.V;} 109 inline void insert_p(int l1,int r1,int l2,int r2,int v){ 110 p[++pnum].l1=l1,p[pnum].r1=r1,p[pnum].val=v,p[pnum].l2=l2,p[pnum].r2=r2,A[pnum].id=pnum,A[pnum].num=v; 111 } 112 int main(){ 113 n=read(),m=read(),Q=read(); 114 for(zkw=1;zkw<=n;zkw<<=1);zkw--; 115 for(i=1;i<n;i++)x=read(),y=read(),insert(x,y); 116 dfs1(1);dfs2(1,1); 117 for(i=1;i<=m;i++){ 118 int u=read(),v=read(),val=read(); 119 if(dfn[u]>dfn[v])swap(u,v); 120 bool flag=(dfn[v]<dfn[u]+size[u]); 121 if(!flag)insert_p(dfn[v],dfn[v]+size[v]-1,dfn[u],dfn[u]+size[u]-1,val); 122 else{ 123 int z=getnext(u,v); 124 if(dfn[z]>1)insert_p(dfn[v],dfn[v]+size[v]-1,1,dfn[z]-1,val); 125 if(dfn[z]+size[z]<=n)insert_p(dfn[z]+size[z],n,dfn[v],dfn[v]+size[v]-1,val); 126 } 127 } 128 sort(A+1,A+1+pnum,cmp2); 129 for(i=1;i<=pnum;i++){ 130 if(i==1||A[i].num!=A[i-1].num)C[++cnt]=A[i].num; 131 p[A[i].id].val=cnt; 132 } 133 sort(p+1,p+1+pnum,cmp); 134 for(i=1;i<=Q;i++){ 135 ask[i].a=read(),ask[i].b=read(),ask[i].K=read(),ask[i].id=i; 136 if(dfn[ask[i].a]>dfn[ask[i].b])swap(ask[i].a,ask[i].b); 137 } 138 sort(ask+1,ask+1+Q,cmp1); 139 int now=0; 140 for(i=1;i<=Q;i++){ 141 a=ask[i].a,b=ask[i].b; 142 143 while(now<pnum&&p[now+1].l1<=dfn[b])++now,change(now,1),q.push((zs1){now,p[now].r1}); 144 while(!q.empty()&&q.top().V<dfn[b])change(q.top().id,0),q.pop(); 145 146 147 ans[ask[i].id]=kth(dfn[a],ask[i].K); 148 } 149 for(i=1;i<=Q;i++)printf("%d ",ans[i]); 150 return 0; 151 }