您的位置:首页 > 其它

【BZOJ3514】Codechef MARCH14 GERALD07加强版,LCT+主席树

2016-08-06 00:27 441 查看
Time:2016.08.06

Author:xiaoyimi

转载注明出处谢谢

传送门

思路:

今天模拟题T3

结果是看都没看??

n,m<=1000

每次直接暴力并查集,O(n)判断

复杂度O(qm)

考虑离线

应该是询问分块排序,类似莫队然后上LCT或者可持久化并查集(口胡get√)

满分做法

考虑LCT这个东西

按照边加入的时间戳维护最小生成树

加入边i(x,y)会形成环时

求出(x,y)所在联通块中时间戳最小的边j并删去(就是最早加入的边)

记录a[i]=j

(注意:如果i为自环,就把a赋值为+∞)

每次处理[l,r]间的询问时

查询[l,r]内,求得a[i]<l的数量

很显然这是主席树可以做的事

连离散化都不用的

注意:无

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define M 200005
#define ls(x) tr[x].ch[0]
#define rs(x) tr[x].ch[1]
using namespace std;
int in()
{
int t=0;char ch=getchar();
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9') t=(t<<3)+(t<<1)+ch-48,ch=getchar();
return t;
}
int n=in(),m=in(),k=in(),lastans,cnt;
bool tp=in(),lazy[M<<1];
int root[M],mi[M<<1],fa[M<<1],son[M<<1][2],siz[M<<1],val[M<<1],stacks[M<<1],a[M];
struct Chairman_tree{
int siz,ch[2];
}tr[M*19];
bool isroot(int x){return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;}
void ct(int x)
{
mi[x]=x;
if (val[mi[x]]>val[mi[son[x][0]]])
mi[x]=mi[son[x][0]];
if (val[mi[x]]>val[mi[son[x][1]]])
mi[x]=mi[son[x][1]];
siz[x]=siz[son[x][0]]+siz[son[x][1]]+1;
}
void pushdown(int x)
{
if (!lazy[x]) return;
swap(son[x][0],son[x][1]);
lazy[son[x][0]]^=1;
lazy[son[x][1]]^=1;
lazy[x]=0;
}
void rorate(int x,bool f)
{
int y=fa[x];
fa[son[x][f]]=y;
son[y][!f]=son[x][f];
fa[x]=fa[y];
if (!isroot(y))
{
if (son[fa[y]][0]==y) son[fa[y]][0]=x;
else son[fa[y]][1]=x;
}
fa[y]=x;
son[x][f]=y;
ct(y);ct(x);
}
void splay(int x)
{
int y,cnt=0,k=x;
stacks[++cnt]=k;
while (!isroot(k)) stacks[++cnt]=k=fa[k];
for (;cnt;cnt--) pushdown(stacks[cnt]);
for (y=fa[x];!isroot(x);y=fa[x])
{
if (isroot(y))
rorate(x,son[y][0]==x);
else if (son[fa[y]][0]==y)
{
if (son[y][0]==x) rorate(y,1);
else rorate(x,0);
rorate(x,1);
}
else
{
if (son[y][1]==x) rorate(y,0);
else rorate(x,1);
rorate(x,0);
}
}
}
void access(int x)
{
for (int y=0;x;y=x,x=fa[x])
splay(x),
son[x][1]=y,
ct(x);
}
void link(int x,int y)
{
access(x);
splay(x);
lazy[x]^=1;
fa[x]=y;
}
void cut(int x,int y)
{
access(x);
splay(x);
lazy[x]^=1;
access(y);
splay(y);
fa[x]=son[y][0]=0;
ct(y);
}
int findroot(int x)
{
access(x);
splay(x);
while (son[x][0]) x=son[x][0];
return x;
}
int ask(int x,int y)
{
access(x);
splay(x);
lazy[x]^=1;
access(y);
splay(y);
return mi[y];
}
void build(int rt,int L,int R,int now,int v)
{
tr[now].siz=tr[rt].siz+1;
if (L==R) return;
int mid=L+R>>1;
if (mid>=v)
rs(now)=rs(rt),
ls(now)=++cnt,
build(ls(rt),L,mid,ls(now),v);
else
ls(now)=ls(rt),
rs(now)=++cnt,
build(rs(rt),mid+1,R,rs(now),v);
}
int get(int L,int R,int begin,int end,int v)
{
if (begin==end) return tr[R].siz-tr[L].siz;
int mid=begin+end>>1;
if (v>mid)
return get(rs(L),rs(R),mid+1,end,v)+tr[ls(R)].siz-tr[ls(L)].siz;
else
return get(ls(L),ls(R),begin,mid,v);
}
main()
{
for (int i=0;i<=n;i++)   val[i]=1<<30;
for (int i=n+1;i<=n+m;i++)  val[i]=i-n;
int x,y,p;
for (int i=1;i<=m;i++)
{
x=in();y=in();
if (x==y) {a[i]=m;continue;}
if (findroot(x)==findroot(y))
p=ask(x,y),
a[i]=p-n,
cut(x,p),
cut(y,p);
link(x,n+i);link(y,n+i);
}
for (int i=0;i<=m;i++) root[i]=++cnt;
for (int i=1;i<=m;i++)
build(root[i-1],0,m,root[i],a[i]);
for (;k;k--)
{
x=in();y=in();
if (tp) x^=lastans,y^=lastans;
printf("%d\n",lastans=n-get(root[x-1],root[y],0,m,x-1));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: