[bzoj4009][HNOI2015]接水果

  论不会整体二分的悲伤。。代码长度感人。。然而似乎并不慢。。

  看到树上路径之间的各种关系大概都会想到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 }
View Code
原文地址:https://www.cnblogs.com/czllgzmzl/p/5152256.html