• 树链剖分 树


    很明显一点,T1树里每一条边都会被选取一次。把T2树的每一条边看成一个线段覆盖。每次找到一个只被覆盖了一次的线段,找到他是被那个区间覆盖的,把那个区间删去。如果最后能删完,就有解,删不完就是无解。 
    搞个树剖维护区间被覆盖的最小次数。但是较难的地方是:如何判断某一条边是被那个区间覆盖的。其实我们可以再维护一个值,把覆盖这个点的区间的编号加起来,因为我们找线段时只是找被覆盖一次的线段,所以一定就是他的编号了。因此在删区间的时候,额外维护这个变量。 
    另一个比较难的地方:找到你要删的那条边后,把它赋成inf,他就不会对答案产生影响了(维护的是区间最小值,0可是比1小的。。),我曾经卡在一个地方,就是在删区间时删出来一个0怎么办。那么这个0一定不会再被那一个区间选择了。但是很明显每条边都是要被选的,那这就一定无解了。 
    注:把边权下放到点时注意把用不到的点赋成无限大。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstdlib>
      4 #include <cstring>
      5 #include <algorithm>
      6 #define N 200005
      7 #define inf 1000000000
      8 #define mem(x) (memset(x,0,sizeof(x)))
      9 #define ll long long
     10 using namespace std;
     11 struct road{int v,next;}lu[N*2];
     12 struct node{int x,y;}a[N];
     13 int T,ans,n,e,cnt,adj[N],f[N],top[N],sz[N],son[N],id[N],dep[N];
     14 void add(int u,int v){lu[++e]=(road){v,adj[u]};adj[u]=e;}
     15 namespace TREE
     16 {
     17     struct tree{int l,r,su,lsu;ll h,lh;}t[N*4];
     18     inline void build(int l,int r,int x)
     19     {
     20         t[x].l=l;t[x].r=r;
     21         t[x].h=t[x].lh=t[x].lsu=t[x].su=0;
     22         if(l==r)return;
     23         int mid=l+r>>1;
     24         build(l,mid,x*2);
     25         build(mid+1,r,x*2+1);
     26     }
     27     inline void down(int x)
     28     {
     29         int h=t[x].lh,su=t[x].lsu;
     30         t[x].lh=t[x].lsu=0;
     31         t[x*2].h+=h;t[x*2].lh+=h;
     32         t[x*2+1].h+=h;t[x*2+1].lh+=h;
     33         t[x*2].su+=su;t[x*2].lsu+=su;
     34         t[x*2+1].su+=su;t[x*2+1].lsu+=su;
     35     }
     36     inline void Q(int x)
     37     {
     38         if(t[x].l==t[x].r){ans=t[x].h,t[x].su=inf;return;}
     39         if(t[x].lh)down(x);
     40         if(t[x*2].su==1)Q(x*2);
     41         else Q(x*2+1);
     42         t[x].su=min(t[x*2].su,t[x*2+1].su);
     43     }
     44     inline void add(int l,int r,int k,ll h,int x)
     45     {
     46         if(t[x].l>=l&&t[x].r<=r)
     47         {
     48             t[x].su+=k;t[x].lsu+=k;
     49             t[x].h+=h;t[x].lh+=h;
     50             if(l==1)t[x].su=inf;
     51             return;
     52         }
     53         if(t[x].lh)down(x);
     54         int mid=t[x].l+t[x].r>>1;
     55         if(l<=mid)add(l,r,k,h,x*2);
     56         if(r>mid)add(l,r,k,h,x*2+1);
     57         t[x].su=min(t[x*2].su,t[x*2+1].su);
     58     }
     59     inline void C(int x,int y,int k,ll h)
     60     {
     61         int fx=top[x],fy=top[y];
     62         while(fx^fy)
     63         {
     64             if(dep[fx]<dep[fy])swap(fx,fy),swap(x,y);
     65             add(id[fx],id[x],k,h,1);
     66             x=f[fx],fx=top[x];
     67         }
     68         if(x==y)return;
     69         if(id[x]>id[y])swap(x,y);
     70         add(id[x]+1,id[y],k,h,1);
     71     }
     72 }
     73 using namespace TREE;
     74 inline void dfs1(int x,int fa)
     75 {
     76     f[x]=fa;sz[x]=1;dep[x]=dep[fa]+1;
     77     for(int i=adj[x];i;i=lu[i].next)
     78     {
     79         int to=lu[i].v;if(to==fa)continue;
     80         dfs1(to,x);sz[x]+=sz[to];
     81         if(sz[to]>sz[son[x]])son[x]=to;
     82     }
     83 }
     84 inline void dfs2(int x,int y)
     85 {
     86     top[x]=y;id[x]=++cnt;
     87     if(!son[x])return;
     88     dfs2(son[x],y);
     89     for(int i=adj[x];i;i=lu[i].next)
     90     {
     91         int to=lu[i].v;
     92         if(to==f[x]||to==son[x])continue;
     93         dfs2(to,to);
     94     }
     95 }
     96 bool check()
     97 {
     98     dfs1(1,0);dfs2(1,1);build(1,n,1);add(1,1,1,inf,1);
     99     for(int i=1;i<n;i++)C(a[i].x,a[i].y,1,i);
    100     for(int i=1;i<n;i++)
    101     {
    102         if(t[1].su!=1)return 0;
    103         ans=0;Q(1);
    104         C(a[ans].x,a[ans].y,-1,-ans);
    105     }
    106     return 1;
    107 }
    108 int main()
    109 {
    110     scanf("%d",&T);
    111     while(T--)
    112     {
    113         scanf("%d",&n);e=cnt=0;
    114         mem(sz);mem(son);mem(f);mem(top);mem(adj);mem(dep);mem(id);
    115         for(int i=1,x,y;i<n;i++)scanf("%d%d",&x,&y),add(x,y),add(y,x);
    116         for(int i=1,x,y;i<n;i++)scanf("%d%d",&x,&y),a[i]=(node){x,y};
    117         if(check())printf("YES
    ");
    118         else printf("NO
    ");
    119     }
    120 }
    View Code
  • 相关阅读:
    Access sql语句创建表及字段类型
    30条HTML代码编写指南 for入门者
    21 个HTML网页转RSS Feeds的工具
    51 个漂亮的电子商务网站设计分享
    如何更改列表项前的New标记的天数设置(daystoshownewicon )
    如何使Layouts里的页面应用站点母板页
    SPCAMLEditor使用系列(2)利用SPCAMLEditor,实现列表顺序号。
    在SharePoint中使用自定义的服务器控件(Web Control)
    开发支持三级目录的导航菜单
    CAML查询时用户类型字段的处理
  • 原文地址:https://www.cnblogs.com/QTY2001/p/7725675.html
Copyright © 2020-2023  润新知