[LCT 树状数组] HDU 5333 Undirected Graph

来源:互联网 发布:vmware12安装linux教程 编辑:程序博客网 时间:2024/06/03 20:11

这个题跟 [LCT 主席树] BZOJ 3514 Codechef MARCH14 GERALD07加强版有异曲同工之妙
考虑询问按右端点排序
对于一条边 边的权值定义为较小的一端的编号
那么显然权值大的边更有利
对于每个右端点 我们加入所有新增的边 维护最大生成树
询问么 就是n-生成树中编号大于等于左端点 因为这样的边会把两个联通块连在一起

#include<cstdio>#include<cstdlib>#include<algorithm>#include<stack>using namespace std;inline char nc(){  static char buf[100000],*p1=buf,*p2=buf;  if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }  return *p1++;}inline bool read(int &x){  char c=nc(),b=1;  for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; else if (c==EOF) return 0;  for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; return 1;}const int N=100005;namespace BIT{  int c[N],maxn;  inline void init(int n){ maxn=n; for (int i=1;i<=n;i++) c[i]=0; }  inline void add(int x,int r){ for (int i=x;i<=maxn;i+=i&-i) c[i]+=r; }  inline int sum(int x){ int ret=0; for (int i=x;i;i-=i&-i) ret+=c[i]; return ret; }  inline int sum(int l,int r){ return sum(r)-sum(l-1); }}int us[N*2],vs[N*2],ws[N*3];inline int Min(int a,int b){  return ws[a]<ws[b]?a:b;}struct node{  node *f,*ch[2];  int idx,v; bool rev;  bool isr() { return !f || (f->ch[0]!=this && f->ch[1]!=this); }  bool dir() { return f->ch[1]==this; }  void setc(node *c,int d) { ch[d]=c; if (c) c->f=this; }  void push() {    if (rev) { swap(ch[0],ch[1]); if(ch[0])ch[0]->rev^=1; if(ch[1])ch[1]->rev^=1; rev=0;}  }  void upd() {    v=idx; if(ch[0])v=Min(v,ch[0]->v); if(ch[1])v=Min(v,ch[1]->v);  }}pool[N*3];inline void rot(node *x){  node *p=x->f; bool d=x->dir();  if (!p->isr()) p->f->setc(x,p->dir()); else x->f=p->f;  p->setc(x->ch[d^1],d); x->setc(p,d^1); p->upd();}stack<node*> sta;inline void splay(node *x){  node *q=x; for (;!q->isr();q=q->f) sta.push(q); sta.push(q);  while (!sta.empty()) sta.top()->push(),sta.pop();  while (!x->isr())    if (x->f->isr()) rot(x);    else if (x->dir()==x->f->dir()) rot(x->f),rot(x);    else rot(x),rot(x);  x->upd();}void expose(node *x){  for (node *q=NULL;x;q=x,x=x->f) splay(x),x->ch[1]=q,x->upd();}void exert(node *x){ expose(x); splay(x); x->rev^=1; }void link(node *x,node *y) { exert(y); y->f=x; }void cut(node *x,node *y) { exert(x); expose(y); splay(y); y->ch[0]=x->f=NULL; y->upd(); }node *frt(node *x){ expose(x),splay(x); for (;x->push(),x->ch[0];x=x->ch[0]); return x; }int query(node *x,node *y){ exert(x); expose(y); splay(y); return y->v; }int n,m;struct abcd{  int l,r,idx;  bool operator < (const abcd &B) const{ return r<B.r; }}eve[N*2];int tot,ans[N];inline void addedge(int i){  if (frt(pool+m+us[i])==frt(pool+m+vs[i])){    int p=query(pool+m+us[i],pool+m+vs[i]);    if (ws[p]<ws[i]){      cut(pool+p,pool+m+us[p]),cut(pool+p,pool+m+vs[p]); BIT::add(ws[p],-1);      link(pool+i,pool+m+us[i]),link(pool+i,pool+m+vs[i]); BIT::add(ws[i],1);    }  }else    link(pool+i,pool+m+us[i]),link(pool+i,pool+m+vs[i]),BIT::add(ws[i],1);}inline int query(int i){  return n-BIT::sum(eve[i].l,eve[i].r);}int main(){  freopen("t.in","r",stdin);  freopen("t.out","w",stdout);  while (read(n)&&read(m)&&read(tot)){    for (int i=1;i<=m;i++) { read(eve[i].l),read(eve[i].r); if (eve[i].l>eve[i].r) swap(eve[i].l,eve[i].r); }    sort(eve+1,eve+m+1);    for (int i=1;i<=m;i++) us[i]=ws[i]=eve[i].l,vs[i]=eve[i].r;    for (int i=m+1;i<=m+n;i++) ws[i]=1<<30;    for (int i=1;i<=m+n;i++) pool[i].idx=pool[i].v=i,pool[i].rev=0,pool[i].f=pool[i].ch[0]=pool[i].ch[1]=NULL;    for (int i=1;i<=tot;i++) read(eve[i].l),read(eve[i].r),eve[i].idx=i;    sort(eve+1,eve+tot+1); int pnt1=1,pnt2=1;    BIT::init(n);    for (int i=1;i<=n;i++){      while (pnt1<=m && vs[pnt1]==i)    addedge(pnt1),pnt1++;      while (pnt2<=tot && eve[pnt2].r==i)    ans[eve[pnt2].idx]=query(pnt2),pnt2++;    }    for (int i=1;i<=tot;i++) printf("%d\n",ans[i]);  }  return 0;}
0 0
原创粉丝点击