您的位置:首页 > 其它

[LCT 树状数组] HDU 5333 Undirected Graph

2017-02-07 16:37 363 查看
这个题跟 [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
,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
;

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: