zoukankan      html  css  js  c++  java
  • uoj407 【IOI2018】狼人

    link

    题意:

    给一张n个点m条边的无向图,有q个询问,每次询问给出s,t,l,r,问你能否从s走到t,并且初始为人形,结束时必须为狼形,你是人形的时候必须避开$[1,l)$的节点,狼形的时候必须避开$(r,n]$的节点,你只能在$[L,R]$的节点处变身?

    $n,qleq  2 imes 10^5,mleq 4 imes 10^5.$

    题解:

    get技能——Kruskal重构树

    重构树是一个类似堆的结构,节点u比它的所有儿子v的权都要来的小/大(在这题中都有用到),可以用并查集建树。

    考虑题中s~t有合法路径相当于,s只经过L~N的点能到达的点集和t只经过1~R的点能到达的点集有交。

    那么考虑建出Kruskal最大/小重构树,那么两个点集分别对应到两棵树上的一个子树,求出dfs序转化成两个区间。

    把每个点对应到一个坐标$[dfn1,dfn2]$(在两棵树中dfs序上的位置),原问题等价于询问一个矩形$x∈[l1,r1],y∈[l2,r2]$中是否有点,离线树状数组即可。

    复杂度$mathcal{O}(nlog n)$。

    code:

     1 #include<bits/stdc++.h>
     2 #include "werewolf.h"
     3 #define rep(i,x,y) for (int i=(x);i<=(y);i++)
     4 #define per(i,x,y) for (int i=(x);i>=(y);i--)
     5 #define ll long long
     6 #define VI vector<int>
     7 using namespace std;
     8 const int N=2e5+5;
     9 int u,v,n,m,Q,top,bit[N]; VI ans,G[N];
    10 struct node{
    11     int x,y,ty,op,id;
    12     node(){}
    13     node(int x,int y,int ty,int op,int id):x(x),y(y),ty(ty),op(op),id(id){}
    14 }q[N*5];
    15 bool cmp(node x,node y){ return x.x<y.x||x.x==y.x&&x.ty<y.ty; }
    16 struct Kruskal_rebuild_tree{
    17     int cnt,head[N],fa[N],clk,in[N],out[N],f[N][19];
    18     struct edge{ int to,nxt; }e[N];
    19     void adde(int x,int y){ e[++cnt].to=y; e[cnt].nxt=head[x]; head[x]=cnt; }
    20     int getfa(int x){ return x==fa[x]?x:fa[x]=getfa(fa[x]); }
    21     void dfs(int u,int ty){
    22         rep (i,1,18) f[u][i]=f[f[u][i-1]][i-1];
    23         in[u]=++clk;
    24         for (int i=head[u];i;i=e[i].nxt) f[e[i].to][0]=u,dfs(e[i].to,ty);
    25         out[u]=clk;
    26     }
    27     void build(int ty){
    28         cnt=0; rep (x,1,n) fa[x]=x,head[x]=0;
    29         if (!ty){
    30             per (x,n,1)
    31                 for (auto y:G[x])
    32                     if (x<y&&getfa(x)!=(y=getfa(y))) adde(x,y),fa[y]=x;
    33         } else{
    34             rep (x,1,n)
    35                 for (auto y:G[x])
    36                     if (x>y&&getfa(x)!=(y=getfa(y))) adde(x,y),fa[y]=x;
    37         }
    38         rep (i,1,n) if (getfa(i)==i) dfs(i,ty);
    39     }
    40     int qry(int x,int lim,int ty){
    41         per (i,18,0)
    42             if (f[x][i]&&(!ty?f[x][i]>=lim:f[x][i]<=lim)) x=f[x][i];
    43         return x;
    44     }
    45 }T[2];
    46 void add(int x){ for (;x<=n;x+=x&-x) bit[x]++; }
    47 int qry(int x){ int s=0; for (;x;x-=x&-x) s+=bit[x]; return s; }
    48 VI check_validity(int _n,VI x,VI y,VI s,VI t,VI l,VI r){
    49     n=_n; m=x.size(),Q=s.size();
    50     rep (i,0,m-1) G[++x[i]].push_back(++y[i]),G[y[i]].push_back(x[i]);
    51     T[0].build(0); T[1].build(1);
    52     rep (i,1,n) q[++top]=node(T[0].in[i],T[1].in[i],0,0,0);
    53     rep (i,0,Q-1){
    54         ++s[i],++t[i],++l[i],++r[i];
    55         int u=T[0].qry(s[i],l[i],0),v=T[1].qry(t[i],r[i],1);
    56         int l1=T[0].in[u],r1=T[0].out[u],l2=T[1].in[v],r2=T[1].out[v];
    57         q[++top]=node(r1,r2,1,1,i);
    58         if (l1>1) q[++top]=node(l1-1,r2,1,-1,i);
    59         if (l2>1) q[++top]=node(r1,l2-1,1,-1,i);
    60         if (l1>1&&l2>1) q[++top]=node(l1-1,l2-1,1,1,i);
    61     }
    62     sort(q+1,q+1+top,cmp); ans.resize(Q);
    63     rep (i,1,top)
    64         if (!q[i].ty) add(q[i].y); else ans[q[i].id]+=qry(q[i].y)*q[i].op;
    65     rep (i,0,Q-1) ans[i]=!!ans[i];
    66     return ans;
    67 }
    View Code
  • 相关阅读:
    HDU 1114 Piggy-Bank
    HDU 2955 Robberies
    NTOJ 290 动物统计(加强版)
    POJ 3624 Charm Bracelet
    HDU 2602 Bone Collector
    POJ 1523 SPF(无向图割顶)
    HDU 5311 Hidden String
    HDU 1421 搬寝室
    HDU 1058 Humble Numbers
    POJ 3259 Wormholes(spfa判负环)
  • 原文地址:https://www.cnblogs.com/bestFy/p/9819838.html
Copyright © 2011-2022 走看看