"Codechef" Chef and Graph Queries

Source: Internet
Author: User

Portal--CC Chef and Graph Queries

Solution

Happy data structure problem (However, there seems to be a very good MO team + can be revoked and check set pointers QWQ)

First, consider a way to make it easier. Calculate the number of Unicom blocks for a graph: we can consider the repulsion, maintain the spanning tree for each connected block, and then \ (n-\) generate the tree edge number is the answer.

It's a good thing to do with the edge, but the light doesn't solve our problems.

? Thinking along this line of thought, regardless of the complexity of the time, for a query, consider the number of \ (L\sim r\) side of a tree added to the 1\sim (l-1\) edge of the resulting trees (regardless of this spanning tree edge selection method) , consider the case where an edge has contributed (becoming part of the new spanning tree):

(1) This edge can be replaced by (1\sim l-1\) an edge

(2) The two endpoints of this edge are not currently connected

? So the question becomes, see how many edges in \ (L\sim r\) can be replaced by the edges in the spanning tree with the number in the ( 1\sim l-1\) range plus the (2) case

At this point, we can determine how the spanning tree is chosen: because there are as many edges as possible to replace it in the \ (1\sim l-1\) range, once the other side can be replaced in the front, we would prefer a small replacement

Again, when considering asking \ ((l,r) \) , we are actually equivalent to getting \ (1\sim r\) spanning Tree (we), so we can preprocess, sequentially add edges, and maintain the current spanning tree with LCT, Then use a chair tree (by weight) to maintain the 1\sim (i\) edge of the spanning tree, each number of edges can be replaced by how many numbered edges, in order to facilitate the query, those who do not need to replace the directly joined Edge Unified Add to \ (0\) position, And then when the query as long as in the first \ (r\) and the (l-1\) tree to check \ ([0,l-1]\) and then subtract a bit, then take \ (n\) to reduce the answer is

And finally, one more thing. Because to support the deletion of the operation, so LCT inside the side also as a point is good ovo

  

The code probably looks like this.

#include <iostream> #include <cstdio> #include <cstring>using namespace Std;const int n=2* (1e5) +10,    Seg=n*20,inf=2147483647;int rec[n][2];int n,m,q,t;namespace lct{/*{{{*/const int n=::n*2;    int ch[n][2],mn[n],fa[n],rev[n],val[n];    void reset (int x) {ch[x][0]=ch[x][1]=0; fa[x]=0; val[x]=mn[x]=inf;    } void Clear (int n) {for (int i=1;i<=n;++i) reset (i);    } bool IsRoot (int x) {return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}    int which (int x) {return ch[fa[x]][1]==x;}        void reverse (int x) {swap (ch[x][0],ch[x][1]);    Rev[x]^=1;        } void Pushdown1 (int x) {if (!rev[x]) return;        if (ch[x][0]) reverse (ch[x][0]);        if (ch[x][1]) reverse (ch[x][1]);    rev[x]=0;        } void Pushdown (int x) {if (!isroot (x)) Pushdown (fa[x]);    PUSHDOWN1 (x);        } void Pushup (int x) {mn[x]=val[x];        if (Ch[x][0]) mn[x]=min (mn[x],mn[ch[x][0]);    if (ch[x][1]) mn[x]=min (mn[x],mn[ch[x][1]);    }void rotate (int x) {int Dir=which (x), f=fa[x];        if (!isroot (f)) Ch[fa[f]][which (f)]=x; FA[X]=FA[F];         Fa[f]=x;        if (ch[x][dir^1]) fa[ch[x][dir^1]]=f;        CH[F][DIR]=CH[X][DIR^1];        Ch[x][dir^1]=f; Pushup (f);    Pushup (x);        } void Splay (int x) {pushdown (x); for (int f=fa[x];!            IsRoot (x); f=fa[x]) {if (!isroot (f)) rotate (which (f) ==which (x)? f:x);        Rotate (x);    } pushup (x);            } void Access (int x) {for (int last=0;x;last=x,x=fa[x]) {splay (x);            Ch[x][1]=last;        Pushup (x);        }} void Make_rt (int x) {access (x);        Splay (x);    reverse (x);        } bool Connected (int X,int y) {if (x==y) return true;        Make_rt (x);        Access (y);        Splay (y);    return fa[x];        } void link (int x,int y) {make_rt (x);        Fa[x]=y;        Access (x);    Splay (x);   } void Cut (int x,int y) {make_rt (x);     Access (y);        Splay (y);        fa[x]=0;        ch[y][0]=0;    Pushup (y);        } int query (int x,int y) {make_rt (x);        Access (y);        Splay (y);    return mn[y];    }}/*}}}*/namespace seg{/*{{{*/int ch[seg][2],sum[seg],rt[seg];    int N,tot;        void Clear () {for (int i=0;i<=tot;++i) ch[i][0]=ch[i][1]=0,sum[i]=0;    tot=0;    } void init (int _n) {clear (); n=_n;}        int newnode (int pre) {ch[++tot][0]=ch[pre][0]; ch[tot][1]=ch[pre][1]; Sum[tot]=sum[pre];    return tot;        } void _insert (int pre,int &x,int d,int lx,int Rx) {x=newnode (pre);        ++SUM[X];        if (LX==RX) return;        int mid=lx+rx>>1;        if (d<=mid) _insert (Ch[pre][0],ch[x][0],d,lx,mid);    else _insert (CH[PRE][1],CH[X][1],D,MID+1,RX);    } void Insert (int pre,int x,int d) {_insert (rt[pre],rt[x],d,1,n);} int _query (int l,int r,int l,int r,int lx,int Rx) {if (! l&&!        R) return 0; if (l<=lx&AMP;&AMP;RX&LT;=R) return sum[r]-sum[l];        int mid=lx+rx>>1,ret=0;        if (l<=mid) ret+=_query (Ch[l][0],ch[r][0],l,r,lx,mid);        if (r>mid) ret+=_query (CH[L][1],CH[R][1],L,R,MID+1,RX);    return ret; } int query (int l,int r,int l,int R) {return _query (rt[l-1],rt[r],l,r,1,n);}}    /*}}}*/void init () {lct::clear (n+m); Seg::init (m+1);}    void debug (int x) {printf ("#%d:\n", X);    for (int i=0;i<=m;++i) printf ("%d", Seg::query (x-1,x,i+1,i+1)); printf ("\ n");}    void Solve () {int x,y,tmp;        for (int i=1;i<=m;++i) {scanf ("%d%d", &rec[i][0],&rec[i][1]); X=REC[I][0];        Y=REC[I][1];            if (x==y) {seg::rt[i]=seg::rt[i-1];        Continue        } lct::val[n+i]=i;            if (lct::connected (x, y)) {tmp=lct::query (x, y);            Lct::cut (REC[I][0],N+TMP);            Lct::cut (REC[I][1],N+TMP);            Lct::link (X,n+i);            Lct::link (Y,n+i);        Seg::insert (i-1,i,tmp+1);     }   else{Lct::link (x,n+i);            Lct::link (Y,n+i);        Seg::insert (i-1,i,0+1);    }//debug (i);    } int l,r;        for (int i=1;i<=q;++i) {scanf ("%d%d", &l,&r);    printf ("%d\n", N-seg::query (L,r,0+1, (L-1) +1));    }}int Main () {#ifndef Online_judge freopen ("a.in", "R", stdin), #endif scanf ("%d", &t);        for (int o=1;o<=t;++o) {scanf ("%d%d%d", &n,&m,&q);        Init ();    Solve (); }}

Codechef Chef and Graph Queries

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.