zoukankan      html  css  js  c++  java
  • lct总结

    lct=long code tree

    推荐博客:https://www.cnblogs.com/flashhu/p/8324551.html,讲得很详细。

    先放题解包,自己的理解会后续加上。

    T1:Cave 洞穴勘测

    板子题,lct的用途之一:维护联通性,相当与一个可以断边的并查集

    T2:树的维护

    用lct维护边权,考虑把边化为点,对边权的处理会有许多便利。也是对类似题提供一个思路。

    回到这题,因为有取负数的操作,考虑再维护一个最小值,下传标记时交换最大值和最小值,再分别取负。

    具体实现见代码

      1 #include<bits/stdc++.h>
      2 #define N 20050
      3 #define cri const register int
      4 using namespace std;
      5 int n;
      6 struct node{int x,y,z,id;}ed[N];
      7 int w[N],w2[N],val[N],val2[N],ch[N][2],fa[N],t1[N],t2[N];
      8 
      9 inline void pr(int g)
     10 {
     11     printf("g:%d fa:%d lc:%d rc:%d val:%d val2:%d w:%d w2:%d t1:%d t2:%d
    ",g,fa[g],ch[g][0],ch[g][1],val[g],val2[g],w[g],w2[g],t1[g],t2[g]);
     12 }
     13 inline void bl(int g)
     14 {
     15     if(!g)return;//down(g);
     16     bl(ch[g][0]);
     17     pr(g);
     18     bl(ch[g][1]);
     19 }
     20 
     21 
     22 inline int Max(cri a,cri b){if(a>b)return a;return b;}
     23 inline int Min(cri a,cri b){if(a<b)return a;return b;}
     24 inline bool nroot(cri x){
     25     return ch[fa[x]][0]==x||ch[fa[x]][1]==x;
     26 }
     27 inline bool Get(cri x){return ch[fa[x]][1]==x;}
     28 inline void push1(cri x){
     29     swap(ch[x][0],ch[x][1]);t1[x]^=1;
     30 }
     31 inline void push2(cri x){
     32     if(!x)return;
     33 //    printf("inp2:");pr(x);
     34     if(x>n)val[x]=-val[x],val2[x]=-val2[x];
     35     swap(w[x],w2[x]),w[x]=-w[x],w2[x]=-w2[x];
     36 //    printf("inp2:");pr(x);
     37     t2[x]^=1;
     38 }
     39 inline void upd(cri x){
     40     w[x]=Max(w[ch[x][0]],w[ch[x][1]]);
     41     w[x]=Max(w[x],val[x]);
     42     w2[x]=Min(w2[ch[x][0]],w2[ch[x][1]]);
     43     w2[x]=Min(w2[x],val2[x]);
     44 }
     45 inline void down(cri x){
     46     if(t1[x]){
     47         push1(ch[x][0]);push1(ch[x][1]);
     48         t1[x]=0;
     49     }
     50     if(t2[x]){
     51         push2(ch[x][0]);push2(ch[x][1]);
     52         t2[x]=0;
     53     }
     54 //    upd(x);
     55 }
     56 inline void rotate(int x){
     57     cri y=fa[x],z=fa[y],p=Get(x),ww=ch[x][p^1];
     58 //    cout<<"y::"<<y<<" "<<w[y]<<endl;
     59 //    cout<<"x::"<<x<<" "<<w[x]<<endl;
     60     if(ww)fa[ww]=y;ch[y][p]=ww;
     61     if(nroot(y))ch[z][Get(y)]=x;fa[x]=z;
     62     fa[y]=x;ch[x][p^1]=y;
     63 
     64     upd(y);upd(x);
     65 
     66 }
     67 inline void pushall(cri x){
     68     if(nroot(x))pushall(fa[x]);
     69     down(x);
     70 }
     71 inline void splay(cri x){
     72     pushall(x);
     73     while(nroot(x)){
     74         cri y=fa[x];
     75         if(nroot(y))Get(x)==Get(y)?rotate(y):rotate(x);
     76         rotate(x);
     77     }
     78     upd(x);
     79 }
     80 inline void access(int x){
     81     for(int y=0;x;x=fa[y=x])splay(x),ch[x][1]=y,upd(x);
     82     upd(x);
     83 }
     84 inline void findroot(int x){
     85     access(x);splay(x);
     86     while(ch[x][0])down(x),x=ch[x][0];
     87     splay(x);
     88 }
     89 inline void makeroot(cri x){access(x);splay(x);push1(x);upd(x);}
     90 inline void link(cri x,cri y){
     91     makeroot(x);fa[x]=y;upd(x);
     92 }
     93 
     94 inline void split(int x,int y){
     95     makeroot(x);makeroot(y);
     96 }
     97 
     98 int main()
     99 {
    100 //    freopen("da.in","r",stdin);
    101     scanf("%d",&n);int m=n;
    102     memset(val,-0x3f,sizeof(val));
    103     memset(w,-0x3f,sizeof(w));
    104     memset(w2,0x3f,sizeof(w2));
    105     memset(val2,0x3f,sizeof(val2));
    106     for(int i=1;i<n;++i){
    107         scanf("%d%d%d",&ed[i].x,&ed[i].y,&ed[i].z);
    108         ed[i].id=++m;
    109         val[m]=val2[m]=ed[i].z;
    110         link(ed[i].x,m);
    111         link(ed[i].y,m);
    112         upd(m);
    113     }
    114 //    for(int i=1;i<=m;++i)bl(i);
    115     string s;
    116     int x,y;
    117     int kkk=0;
    118     while(1)
    119     {
    120 //        printf("kkk:%d
    ",++kkk);
    121         cin>>s;
    122         if(s[0]=='D')return 0;
    123         scanf("%d%d",&x,&y);
    124         if(s[0]=='C')
    125         {
    126             makeroot(ed[x].id);
    127             val[ed[x].id]=y;
    128             val2[ed[x].id]=y;
    129             upd(ed[x].id);
    130         }
    131         else if(s[0]=='N')
    132         {
    133             split(x,y);
    134             push2(y);
    135 //            bl(y);puts("yessssssssssssssssssssssssssss");
    136 //            pr(0);
    137         }
    138         else
    139         {
    140             split(x,y);
    141             printf("%d
    ",w[y]);
    142 //            bl(y);
    143         }
    144     }
    145 }
    View Code

    T3:tree

    此题为对懒标记的考察。因为要用到加法标记和乘法标记,一开始我想开vector统计标记,然后就MLE了。真kx。其实仔细思考一下,发现,可以先下放乘法标记,再下放加法标记

    加入新的加法标记时直接在原加法标记上累加。加入乘法标记时,当前点所有的加法标记都要乘加入的乘法标记,然后再将原乘法标记乘加入的乘法标记。

    然后只维护一个加法标记和一个乘法标记即可,注意开unsigned

    T4:水管局长加强版

    lct维护边权,因为是图,删掉边后难以找到要加入的边,考虑时光倒流。先把所有能够加入的边加入lct,用lct维护一棵最小生成树。

    在新加入边时先查询lct中对应两点是否连通,若联通则看路径上的最大边权和要加入边的边权的大小关系。

    具体实现见代码

      1 #include<bits/stdc++.h>
      2 #define N 1200000
      3 #define cri const register int
      4 using namespace std;
      5 int n,m,q;
      6 int fa[N],ch[N][2],w[N],val[N],t1[N];
      7 struct node{int x,y,z,pd;}ed[N],qq[100050];
      8 unordered_map<long long,int>h;
      9 inline void pr(int x){
     10     printf("x:%d f:%d l:%d r:%d v:%d w:%d t1:%d
    ",x,fa[x],ch[x][0],ch[x][1],val[x],w[x],t1[x]);
     11 }
     12 inline int Get(cri x){
     13     return ch[fa[x]][1]==x;
     14 }
     15 inline int nroot(cri x){
     16     return ch[fa[x]][0]==x||ch[fa[x]][1]==x;
     17 }
     18 inline void upd(cri x){
     19     w[x]=max(w[ch[x][0]],w[ch[x][1]]);
     20     w[x]=max(w[x],val[x]);
     21 }
     22 inline void push1(cri x){
     23     swap(ch[x][0],ch[x][1]);t1[x]^=1;
     24 }
     25 inline void down(cri x){
     26     if(t1[x])push1(ch[x][0]),push1(ch[x][1]),t1[x]=0;
     27 }
     28 inline void rotate(cri x){
     29     cri y=fa[x],z=fa[y],p=Get(x),w=ch[x][p^1];
     30     if(w)fa[w]=y;ch[y][p]=w;
     31     if(nroot(y))ch[z][Get(y)]=x;fa[x]=z;
     32     fa[y]=x;ch[x][p^1]=y;
     33     upd(y);upd(x);
     34 }
     35 inline void pushall(cri x){
     36     if(nroot(x))pushall(fa[x]);down(x);
     37 }
     38 inline void splay(cri x){
     39     pushall(x);
     40     while(nroot(x)){
     41         cri y=fa[x];
     42         if(nroot(y))Get(y)==Get(x)?rotate(y):rotate(x);
     43         rotate(x);
     44     }
     45 }
     46 inline void access(int x){
     47     for(int y=0;x;x=fa[y=x])splay(x),ch[x][1]=y,upd(x);
     48 }
     49 inline void makeroot(cri x){
     50     access(x);splay(x);push1(x);
     51 }
     52 inline void split(cri x,cri y){
     53     makeroot(x);access(y);splay(y);
     54 }
     55 inline void link(cri x,cri y){
     56     makeroot(x);fa[x]=y;
     57 }
     58 inline void cut(cri x,cri y){
     59     split(x,y);ch[y][0]=fa[x]=0;upd(y);
     60 }
     61 inline int findroot(int x){
     62     while(ch[x][0])down(x),x=ch[x][0];
     63     splay(x);return x;
     64 }
     65 inline bool linked(cri x,cri y){
     66     split(x,y);return findroot(y)==x;
     67 }
     68 
     69 inline int getma(cri x,cri y){
     70     split(x,y);return w[y];
     71 }
     72 inline int find(int x){
     73     while(1){
     74         if(w[x]==val[x])return x;
     75         x=w[x]==w[ch[x][0]]?ch[x][0]:ch[x][1];
     76     }
     77 }
     78 
     79 inline void add(node e,int id){
     80 //    if(id==8){
     81 //        for(int i=1;i<=n+m;++i)pr(i);
     82 //        puts("noooooo");
     83 //    }
     84     if(!linked(e.x,e.y)){
     85     //    puts("nothere");
     86         val[id]=e.z;
     87         link(e.x,id);
     88         link(e.y,id);
     89         upd(id);
     90     }
     91     else{
     92         int t=getma(e.x,e.y);
     93         if(t>e.z){
     94     //        puts("yess");
     95             t=find(e.y);
     96 //            cout<<"t:"<<t<<endl;
     97             split(ed[t-n].x,ed[t-n].y);
     98             splay(t);
     99             fa[ch[t][0]]=fa[ch[t][1]]=0;
    100             val[id]=e.z;
    101             link(e.x,id);
    102             link(e.y,id);
    103             upd(id);
    104         }
    105     }
    106 }
    107 int main()
    108 {
    109 //    freopen("da.in","r",stdin);
    110     scanf("%d%d%d",&n,&m,&q);
    111     for(int i=1;i<=m;++i){
    112         scanf("%d%d%d",&ed[i].x,&ed[i].y,&ed[i].z);
    113         if(ed[i].x>ed[i].y)swap(ed[i].x,ed[i].y);
    114         h[1ll*ed[i].x*n+ed[i].y]=i;
    115     }
    116     for(int i=1;i<=q;++i){
    117         scanf("%d%d%d",&qq[i].pd,&qq[i].x,&qq[i].y);
    118         if(qq[i].pd==2){
    119             if(qq[i].x>qq[i].y)swap(qq[i].x,qq[i].y);
    120             qq[i].z=h[1ll*qq[i].x*n+qq[i].y];
    121             ed[qq[i].z].pd=1;
    122         }
    123     }
    124 //    puts("ed");
    125     for(int i=1;i<=m;++i)
    126         if(!ed[i].pd)add(ed[i],i+n);
    127 //    puts("ed2");
    128     for(int i=q;i;--i){
    129 //        cout<<i<<endl;
    130 //        if(i==1||i==2){
    131 //            for(int j=1;j<=n+m;++j)pr(j);
    132 //            puts("yes");
    133 //        }
    134         if(qq[i].pd==1){
    135             qq[i].z=getma(qq[i].x,qq[i].y);
    136         }
    137         else{
    138 //            cout<<"i"<<i<<" "<<qq[i].z<<endl;
    139             add(ed[qq[i].z],qq[i].z+n);
    140         }
    141     }
    142 //    puts("ed3");
    143     for(int i=1;i<=q;++i){
    144         if(qq[i].pd==1){
    145             printf("%d
    ",qq[i].z);
    146         }
    147     }
    148     return 0;
    149 }
    View Code

    T5:GERALD07加强版

    一开始看见这题挺蒙的,用lct维护一段区间内的边。然后发现根本不可做。

    考虑求连通块个数可以点数减去边数,但这只适用于森林,对于图根本不可行。

    那么是不是删掉一些边把图转换为树就可以点数减边数了?

    考虑从前往后加边,用lct维护连通性,新加入一个边时,查询原lct中两点是否联通,

    若已经联通则找到路径上编号最小的边(记为pre)删掉,并加入主席树进行维护。

    代表的含义就是:当前边与pre同时出现时,当前边不会作贡献

    维护主席树,在每个点插入对应的pre,查询是直接在右端点处的主席树查询从左端点到右端点有多少个pre

    即为当前区间被干掉了多少条边。

    注:自环的pre为自己,自环不能加入lct

      1 #include<bits/stdc++.h>
      2 #define N 400050
      3 #define lc ch[x][0]
      4 #define rc ch[x][1]
      5 using namespace std;
      6 int n,m,k;
      7 int fa[N],ch[N][2],w[N],val[N],t1[N];
      8 inline void pr(int x){
      9     printf("x:%d f:%d l:%d r:%d v:%d w:%d t:%d
    ",x,fa[x],lc,rc,val[x],w[x],t1[x]);
     10 }
     11 inline int Get(int x){
     12     return ch[fa[x]][1]==x;
     13 }
     14 inline int nroot(int x){
     15     return ch[fa[x]][0]==x||ch[fa[x]][1]==x;
     16 }
     17 inline void push1(int x){
     18     swap(lc,rc);t1[x]^=1;
     19 }
     20 inline void down(int x){
     21     if(t1[x])push1(lc),push1(rc),t1[x]^=1;
     22 }
     23 inline void upd(int x){
     24     w[x]=min(w[lc],w[rc]);w[x]=min(w[x],val[x]);
     25 }
     26 inline void rotate(int x){
     27     int y=fa[x],z=fa[y],p=Get(x),w=ch[x][p^1];
     28     if(w)fa[w]=y;ch[y][p]=w;
     29     if(nroot(y))ch[z][Get(y)]=x;fa[x]=z;
     30     fa[y]=x;ch[x][p^1]=y;
     31     upd(y);upd(x);
     32 }
     33 void pushall(int x){
     34     if(nroot(x))pushall(fa[x]);down(x);
     35 }
     36 inline void splay(int x){
     37     pushall(x);
     38     while(nroot(x)){
     39         int y=fa[x];
     40         if(nroot(y))Get(x)==Get(y)?rotate(y):rotate(x);
     41         rotate(x);
     42     }
     43 }
     44 inline void access(int x){
     45     for(int y=0;x;x=fa[y=x])splay(x),rc=y,upd(x);
     46 }
     47 inline void makeroot(int x){
     48     access(x);splay(x);push1(x);
     49 }
     50 inline void split(int x,int y){
     51     makeroot(x);access(y);splay(y);
     52 }
     53 inline void link(int x,int y){
     54     makeroot(x);fa[x]=y;
     55 }
     56 inline void cut(int x,int y){
     57     split(x,y);ch[y][0]=fa[x]=0;upd(y);
     58 }
     59 inline int findroot(int x){
     60     while(lc)down(x),x=lc;splay(x);return x;
     61 }
     62 inline bool linked(int x,int y){
     63     split(x,y);return findroot(y)==x;
     64 }
     65 struct node{
     66     int x,y,pre;
     67 }ed[N];
     68 #undef lc
     69 #undef rc
     70 struct hjt{
     71     int rt[N],lc[N*20],rc[N*20],sum[N*20],tot;
     72     inline void upd(int g){
     73         sum[g]=sum[lc[g]]+sum[rc[g]];
     74     }
     75     inline void add(int &g,int f,int l,int r,int x){
     76         if(!g)g=++tot;
     77         sum[g]=sum[f]+1;
     78         if(l==r)return;
     79         const int m=l+r>>1;
     80         if(x<=m)rc[g]=rc[f],add(lc[g],lc[f],l,m,x);
     81         else lc[g]=lc[f],add(rc[g],rc[f],m+1,r,x);
     82         upd(g);
     83     //    printf("g:%d f:%d l:%d r:%d s:%d
    ",g,f,lc[g],rc[g],sum[g]);
     84     }
     85     inline int ask(int g,int l,int r,int x,int y){
     86         if(!g)return 0;
     87         if(l>=x&&r<=y)return sum[g];
     88         if(l>y||r<x)return 0;
     89         const int m=l+r>>1;
     90         return ask(lc[g],l,m,x,y)+ask(rc[g],m+1,r,x,y);
     91     }
     92 }k2;
     93 inline int add(int id,node e){
     94     if(!linked(e.x,e.y)){
     95         val[id]=id-n;
     96         link(id,e.x);
     97         link(id,e.y);
     98         return 0;
     99     }
    100     else{
    101         split(e.x,e.y);int ret=w[e.y];
    102         int t=ret+n;
    103         split(ed[ret].x,ed[ret].y);
    104         splay(t);
    105         fa[ch[t][0]]=fa[ch[t][1]]=0;
    106         val[id]=id-n;
    107         link(id,e.x);
    108         link(id,e.y);
    109         return ret;
    110     }
    111 }
    112 int main(){
    113 //    freopen("da.in","r",stdin);
    114     //freopen("my.out","w",stdout);
    115     memset(val,0x3f,sizeof(val));
    116     memset(w,0x3f,sizeof(w));
    117     int type;
    118     scanf("%d%d%d%d",&n,&m,&k,&type);
    119     for(int i=1;i<=m;++i){
    120         scanf("%d%d",&ed[i].x,&ed[i].y);
    121         if(ed[i].x==ed[i].y)ed[i].pre=i;
    122         else ed[i].pre=add(i+n,ed[i]);
    123 
    124         if(ed[i].pre)k2.add(k2.rt[i],k2.rt[i-1],1,m,ed[i].pre);
    125         else k2.rt[i]=k2.rt[i-1];
    126     //    printf("pre[%d]=%d
    ",i,ed[i].pre);
    127     }
    128     for(int i=1,ans=0,x,y;i<=k;++i){
    129         scanf("%d%d",&x,&y);
    130         if(type)x^=ans,y^=ans;ans=n;
    131         ans-=y-x+1-k2.ask(k2.rt[y],1,m,x,y);
    132         printf("%d
    ",ans);
    133     }
    134     return 0;
    135 }
    View Code
  • 相关阅读:
    进程控制
    进程的状态与转换
    进程的概念和特征
    操作系统的体系结构:大内核和微内核
    系统调用
    中断和异常
    【转】Java-----jar反编译修改重新打包
    [转] Android Volley完全解析(一),初识Volley的基本用法
    [转] This Android SDK requires Android Developer Toolkit version 23.0.0 or above
    Can't bind to local 8700 for debugger报错和解决
  • 原文地址:https://www.cnblogs.com/loadingkkk/p/12075194.html
Copyright © 2011-2022 走看看