• [BZOJ3514]CodeChef MARCH14 GERALD07加强版(LCT+主席树)


    3514: Codechef MARCH14 GERALD07加强版

    Time Limit: 60 Sec  Memory Limit: 256 MB
    Submit: 2177  Solved: 834
    [Submit][Status][Discuss]

    Description

    N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数。

    Input

    第一行四个整数N、M、K、type,代表点数、边数、询问数以及询问是否加密。
    接下来M行,代表图中的每条边。
    接下来K行,每行两个整数L、R代表一组询问。对于type=0的测试点,读入的L和R即为询问的L、R;对于type=1的测试点,每组询问的L、R应为L xor lastans和R xor lastans。

    Output

     K行每行一个整数代表该组询问的联通块个数。

    Sample Input

    3 5 4 0
    1 3
    1 2
    2 1
    3 2
    2 2
    2 3
    1 5
    5 5
    1 2

    Sample Output

    2
    1
    3
    1

    HINT

     

    对于100%的数据,1≤N、M、K≤200,000。


    2016.2.26提高时限至60s

     

    Source

    用LCT求出NTR数组,然后主席树在线查询即可,比较简洁巧妙。

    http://hzwer.com/4358.html

    不过是两个高级数据结构合在一起,而且不是嵌套,理论上很好写。

    实际上犯了很多低级错误,而且非常难调,以后一定要慢点写代码。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #define lc ch[x][0]
     4 #define rc ch[x][1]
     5 #define rep(i,l,r) for (int i=l; i<=r; i++)
     6 using namespace std;
     7 
     8 const int N=400100,K=200100,M=4000100,inf=1000000000;
     9 int n,m,Q,op,l,r,x,u,v,nd,ans,fa[N],ntr[K],root[K];
    10 struct E{ int u,v; }e[K];
    11 int find(int x){ return (fa[x]==x) ? x : fa[x]=find(fa[x]); }
    12 
    13 struct LCT{
    14     int v[N],mn[N],s[N],ch[N][2],f[N],tag[N];
    15     bool isroot(int x){ return (!f[x]) || ((ch[f[x]][0]!=x) && (ch[f[x]][1]!=x)); }
    16     void rev(int x){ swap(ch[x][0],ch[x][1]); tag[x]^=1; }
    17     void push(int x){ if (tag[x]) rev(lc),rev(rc),tag[x]=0; }
    18     void pd(int x){ if (!isroot(x)) pd(f[x]); push(x); }
    19     
    20     void upd(int x){
    21         mn[x]=x;
    22         if (v[mn[lc]]<v[mn[x]]) mn[x]=mn[lc];
    23         if (v[mn[rc]]<v[mn[x]]) mn[x]=mn[rc];
    24     }
    25     
    26     void rot(int x){
    27         int y=f[x],z=f[y],w=ch[y][1]==x;
    28         if (!isroot(y)) ch[z][ch[z][1]==y]=x;
    29         f[x]=z; f[y]=x; f[ch[x][w^1]]=y;
    30         ch[y][w]=ch[x][w^1]; ch[x][w^1]=y; upd(y);
    31     }
    32     
    33     void splay(int x){
    34         pd(x);
    35         while (!isroot(x)){
    36             int y=f[x],z=f[y];
    37             if (!isroot(y)){ if ((ch[z][0]==y)^(ch[y][0]==x)) rot(x); else rot(y); }
    38             rot(x);
    39         }
    40         upd(x);
    41     }
    42     
    43     void access(int x){ for (int y=0; x; y=x,x=f[x]) splay(x),ch[x][1]=y,upd(x); }
    44     void mkroot(int x){ access(x); splay(x); rev(x);}
    45     void link(int x,int y){ mkroot(x); f[x]=y; }
    46     void cut(int x,int y){ mkroot(x); access(y); splay(y); ch[y][0]=f[x]=0; upd(y); }
    47     int que(int x,int y){ mkroot(x); access(y); splay(y); return mn[y]; }
    48 }T;
    49 
    50 struct S{
    51     int ls[M],rs[M],sm[M];
    52     
    53     void ins(int y,int &x,int L,int R,int pos){
    54         x=++nd; ls[x]=ls[y]; rs[x]=rs[y]; sm[x]=sm[y]+1;
    55         if (L==R) return; int mid=(L+R)>>1;
    56         if (pos<=mid) ins(ls[y],ls[x],L,mid,pos); else ins(rs[y],rs[x],mid+1,R,pos);
    57     }
    58     
    59     int que(int x,int y,int L,int R,int k){
    60         if (R==k){ return sm[y]-sm[x]; }
    61         int mid=(L+R)>>1;
    62         if (k<=mid) return que(ls[x],ls[y],L,mid,k);
    63             else return sm[ls[y]]-sm[ls[x]]+que(rs[x],rs[y],mid+1,R,k);
    64     }
    65 }S;
    66 
    67 void Kruskal(){
    68     int tot=n;
    69     rep(i,1,n) fa[i]=i;
    70     rep(i,1,m){
    71         int u=e[i].u,v=e[i].v,x=find(u),y=find(v);
    72         if (u==v) { ntr[i]=i; continue; }
    73         if (x==y){
    74             int t=T.que(u,v),k=T.v[t];
    75             ntr[i]=k; T.cut(e[k].u,t); T.cut(e[k].v,t);
    76         }else fa[x]=y;
    77         tot++; T.mn[tot]=tot; T.v[tot]=i;
    78         T.link(u,tot); T.link(v,tot);
    79     }
    80     rep(i,1,m) S.ins(root[i-1],root[i],0,m,ntr[i]);
    81 }
    82 
    83 void solve(){
    84     rep(i,1,Q){
    85         scanf("%d%d",&l,&r);
    86         if (op) l^=ans,r^=ans;
    87         printf("%d
    ",ans=n-S.que(root[l-1],root[r],0,m,l-1));
    88     }
    89 }
    90 
    91 int main(){
    92     freopen("bzoj3514.in","r",stdin);
    93     freopen("bzoj3514.out","w",stdout);
    94     scanf("%d%d%d%d",&n,&m,&Q,&op);
    95     T.v[0]=inf; rep(i,1,n) T.mn[i]=i,T.v[i]=inf;
    96     rep(i,1,m) scanf("%d%d",&e[i].u,&e[i].v);
    97     Kruskal(); solve();
    98     return 0;
    99 } 
  • 相关阅读:
    优秀大数据GitHub项目一览
    自定义组件-BreadcrumbTreeView 的使用
    IOS中的属性列表----Property List
    即时通讯之smack客户端配置
    Android studio 使用问题汇总
    触摸事件UITouch的应用
    Android界面设计之对话框——定制Toast、AlertDialog
    android_orm框架之greenDAO(一)
    火速提升Android仿真器的运行速度 ——仿真器Genymotion
    Android 中的缓存机制与实现
  • 原文地址:https://www.cnblogs.com/HocRiser/p/8552656.html
Copyright © 2020-2023  润新知