zoukankan      html  css  js  c++  java
  • [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
  • 相关阅读:
    旅行计划
    两只塔姆沃斯牛
    迷宫
    异或序列
    异或之和
    素数个数
    SAC E#1
    [JSOI2010]Group 部落划分 Group
    [USACO12FEB]附近的牛Nearby Cows
    [HNOI2008]Cards
  • 原文地址:https://www.cnblogs.com/czllgzmzl/p/5152256.html
Copyright © 2011-2022 走看看