您的位置:首页 > 其它

bzoj3514

2016-03-07 17:16 211 查看
lct + 主席树

(这个ntr数组 吼啊 有道(zhe)理 污拉拉。。

姑且就叫ntr算法咯。。

#include <cstdio>
#include <iostream>
#include <algorithm>

using namespace std;

int n,m,k,ty;

int ch[400010][2],fa[400010],rv[400010],x[400010],mi[400010];
int st[400010],tp;

struct data {
int x,ord;
bool operator < (const data &b)const {
return x < b.x;
}
}ntr[200010];

struct edge {
int u,v;
}e[200010];
int head[200010];

struct seg {
int ls,rs,l,r,sum;
}tr[4400010];
int cnt;
int rt[200010],last;

int read_int () {
char c = getchar();
int re = 0;
for(;c > '9' || c < '0';c = getchar());
for(;c >= '0' && c <= '9';c = getchar())
re = re * 10 + c - '0';
return re;
}

int find (int u) {
if(u == head[u])
return u;
return head[u] = find(head[u]);
}

void pu (int u) {
mi[u] = x[u];
mi[u] = min(mi[u],mi[ch[u][1]]);
mi[u] = min(mi[u],mi[ch[u][0]]);
}

void reverse (int u) {
int t = ch[u][0];
ch[u][0] = ch[u][1];
ch[u][1] = t;
rv[u] ^= 1;
}

void pd (int u) {
if(!rv[u])
return;
rv[u] = 0;
reverse(ch[u][0]);
reverse(ch[u][1]);
}

void rot (int u,int d) {
ch[fa[u]][d ^ 1] = ch[u][d];
if(ch[u][d])
fa[ch[u][d]] = fa[u];
int t = fa[fa[u]];
fa[fa[u]] = u;
ch[u][d] = fa[u];
fa[u] = t;

pu(ch[u][d]);
pu(u);

if(!t)
return;
if(ch[t][0] == ch[u][d])
ch[t][0] = u;
if(ch[t][1] == ch[u][d])
ch[t][1] = u;
}

void splay (int u) {
st[tp = 1] = u;
int t = u;
while(ch[fa[t]][0] == t || ch[fa[t]][1] == t) {
t = fa[t];
st[++tp] = t;
}
while(tp)
pd(st[tp--]);

while(ch[fa[u]][0] == u || ch[fa[u]][1] == u) {
if(ch[fa[fa[u]]][0] != fa[u] && ch[fa[fa[u]]][1] != fa[u]) {
if(ch[fa[u]][0] == u)
rot(u,1);
else rot(u,0);
}
else {
int d = ch[fa[fa[u]]][0] == fa[u];
if(ch[fa[u]][d] == u) {
rot(u,d ^ 1);
rot(u,d);
}
else {
rot(u,d);
rot(u,d);
}
}
}
}

void access (int u) {
int v = 0;
while(u) {
splay(u);
ch[u][1] = v;
pu(u);
v = u;
u = fa[u];
}
}

void mtr (int u) {
access(u);
splay(u);
reverse(u);
}

void link (int u,int v) {
mtr(u);
mtr(v);
fa[u] = v;
}

void cut (int u,int v) {
mtr(v);
access(v);
splay(u);
fa[u] = 0;
}

void push_up (int M) {
tr[M].sum = tr[tr[M].ls].sum + tr[tr[M].rs].sum;
}

void build_ori (int l,int r,int M) {
tr[M].l = l;
tr[M].r = r;
if(l == r)
return;
int mid = (l + r) / 2;
tr[M].ls = ++cnt;
build_ori(l,mid,tr[M].ls);
tr[M].rs = ++cnt;
build_ori(mid + 1,r,tr[M].rs);
}

void build (int last,int ord,int M) {
tr[M].l = tr[last].l;
tr[M].r = tr[last].r;
if(tr[M].l == tr[M].r) {
tr[M].sum = 1;
return;
}

int mid = (tr[M].r + tr[M].l) / 2;
if(ord > mid) {
tr[M].ls = tr[last].ls;
tr[M].rs = ++cnt;
build(tr[last].rs,ord,tr[M].rs);
}
else {
tr[M].rs = tr[last].rs;
tr[M].ls = ++cnt;
build(tr[last].ls,ord,tr[M].ls);
}
push_up(M);
}

int find_ans (int l,int r,int M) {
if(l == tr[M].l && tr[M].r == r)
return tr[M].sum;
int mid = (tr[M].l + tr[M].r) / 2;
if(l > mid)
return find_ans(l,r,tr[M].rs);
else {
if(r <= mid)
return find_ans(l,r,tr[M].ls);
else return find_ans(l,mid,tr[M].ls) + find_ans(mid + 1,r,tr[M].rs);
}
}

int main () {
n = read_int();
m = read_int();
k = read_int();
ty = read_int();

for(int i = 0;i <= n;++i) {
x[i] = mi[i] = 0x3f3f3f3f;
head[i] = i;
}

for(int i = 1;i <= m;++i) {
ntr[i].ord = i;
e[i].u = read_int();
e[i].v = read_int();
if(e[i].u == e[i].v) {
ntr[i].x = i;
continue;
}
if(find(e[i].u) == find(e[i].v)) {
mtr(e[i].u);
access(e[i].v);
splay(e[i].u);
ntr[i].x = mi[e[i].u];
cut(e[ntr[i].x].u,ntr[i].x + n);
cut(e[ntr[i].x].v,ntr[i].x + n);
}
else head[find(e[i].u)] = find(e[i].v);
x[n + i] = mi[n + i] = i;
link(n + i,e[i].u);
link(n + i,e[i].v);
}

sort(ntr + 1,ntr + 1 + m);

rt[0] = last = cnt = 1;

build_ori(1,m,1);

for(int i = 1;i <= m;++i) {
if(ntr[i].x != ntr[i - 1].x) {
for(int j = ntr[i - 1].x + 1;j < ntr[i].x;++j)
rt[j] = last;
}
build(last,ntr[i].ord,rt[ntr[i].x] = ++cnt);
last = rt[ntr[i].x];
}

for(int i = ntr[m].x + 1;i <= m;++i) {
rt[i] = last;
}

int L,R,ans = 0;

for(int i = 1;i <= k;++i) {
L = read_int();
R = read_int();
if(ty) {
L ^= ans;
R ^= ans;
}
ans = n - find_ans(L,R,rt[L - 1]);
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: