loj558&loj2011

loj 2011

题意:一棵树 有两种操作 1.选定一个点 且这个点的权值随着时间的增加而增加1

             2.查询一条路径上点的个数和权值大于C的个数

题解:刚开始没想到离线的做法 认为可以大力线段树 n(logn)^3 然而显然过不去 被韦神教育后也考虑过树上莫队的写法 然而n^(5/3)然并卵 偷偷瞄了一眼题解

发现我们可以这样离线一下 然后少掉一个log 对于每个querty我们找到临界位置max(0,i-C-1) 这样的话 我们只要去找当临界位置的时候在这条链上的被更新的点的个数 这样的话 我们树状数组维护就ojbk了

#include 
#define ll long long
#define s second
#define f first
#define pii pair
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
const int MAXN=2e5+10;
using namespace std;
vectorvec[MAXN];
int son[MAXN],fa[MAXN],num[MAXN],dep[MAXN];
int n,q;
void dfs1(int v,int pre,int deep){
	num[v]=1;dep[v]=deep+1;fa[v]=pre;
	for(int i=0;i0;i-=get_id(i)) ans+=d[i];
	return ans;
}
typedef struct node{
	int u,v,id,p;
	friend bool operator<(node aa,node bb){
		return aa.pdep[v]) swap(u,v);
	ans+=(p[v]-p[u]+1);
	return ans;
}
int get2(int u,int v){
	int uu=tp[u];int vv=tp[v];
	int ans=0;
	while(uu!=vv){
		if(dep[uu]dep[v]) swap(u,v);
	ans+=(querty(p[v])-querty(p[u]-1));
	return ans;
}
node que[MAXN];
bool pd[MAXN];
pii ans1[MAXN];
int vis[MAXN];
int main(){
	scanf("%d",&n);int rt;
	int t;
	for(int i=1;i<=n;i++){
		scanf("%d",&t);son[i]=-1;
		if(t==0){
			rt=i;continue;
		}
		vec[i].push_back(t);
		vec[t].push_back(i);
	}cnt=0;
	int cnt1=0;
	dfs1(rt,0,0);dfs2(rt,rt);
	scanf("%d",&q);
	int op,u,v,c;
	for(int i=1;i<=q;i++){
		scanf("%d",&op);
		if(op==1){
			scanf("%d%d%d",&u,&v,&c);
			ans1[i].f=get1(u,v);
			que[++cnt1].u=u;que[cnt1].v=v;que[cnt1].p=max(0,i-c-1);que[cnt1].id=i;
		}
		else{
			scanf("%d",&u);
			if(pd[u]) continue;
			vis[i]=u;pd[u]=1;
		}
	}
	sort(que+1,que+cnt1+1);
	int _=1;
	for(int i=0;i<=q;i++){
		if(vis[i]) add(p[vis[i]]);
		for(;_<=cnt1&&que[_].p==i;_++){
			ans1[que[_].id].s=get2(que[_].u,que[_].v);
		}
	}
//	if(_<=cnt1){
//		for(;_<=cnt1;_++){
//			ans1[que[_].id].s=get2(que[_].u,que[_].v);
//		}
//	}
	for(int i=1;i<=q;i++)if(!vis[i]) printf("%d %d\n",ans1[i].f,ans1[i].s);
	return 0;
}

 loj 558

 题意:有一个森林 初始时刻每个点都是白色的  现在有四种操作

    1.对于u颜色反转

    2.连接u,v

    3.断开u,v

    4.查询与u联通的所有黑点到u的距离的和

题解:大概很巧妙的是LCT维护子树信息 然后维护LCT维护当前节点的这段链上的贡献 注意反转的时候交换就行了 (但是这个题很毒 指针版本的LCT会A掉 然而数组版本的会T 虽然数组版本的没有A掉 就当作练习了

#include 
#include 
#include 
#include 
#define pii pair
#define il inline
#define f first
#define s second
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,l,r) for(int i=l;i>=r;i--)
#define ll long long
#define rg register
const int MAXN=5e5+10;
using namespace std;
il int read() {
	rg int x=0,f=1;
	rg char ch=getchar();
	while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
	while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
	return x*f;
}
int ch[MAXN][2],cnt,res[MAXN],pre[MAXN],st[MAXN],tp;
ll sum[MAXN],chsum[MAXN],ke[MAXN],rsum[MAXN],num[MAXN],chnum[MAXN],vul[MAXN],size[MAXN];
bool rt[MAXN],key[MAXN];
il void reverse(int r) {
	if(!r) return ;
	std::swap(ch[r][0],ch[r][1]);
	std::swap(sum[r],rsum[r]);
	res[r]^=1;
}
il void push(int x) {
	if(res[x]) {
		reverse(ch[x][0]);
		reverse(ch[x][1]);
		res[x]=0;
	}
}
il void up(int x) {
	if(!x) return ;
	size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
	num[x]=num[ch[x][0]]+num[ch[x][1]]+chnum[x]+key[x];
	vul[x]=vul[ch[x][0]]+vul[ch[x][1]]+ke[x];
	rsum[x]=rsum[ch[x][0]]+rsum[ch[x][1]]+chsum[x]+1ll*(vul[ch[x][1]]+ke[x])*(num[ch[x][0]]+chnum[x]+key[x]);
	sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+chsum[x]+1ll*(vul[ch[x][0]]+ke[x])*(num[ch[x][1]]+chnum[x]+key[x]);
}
il void P(int x) {
	rg int i;
	st[++tp]=x;
	for(i=x; !rt[i]; i=pre[i]) st[++tp]=pre[i];
	for(; tp; tp--) push(st[tp]);
}
il void rotate(int x,int kind) {
	rg int y=pre[x];
	ch[y][!kind]=ch[x][kind];
	pre[ch[x][kind]]=y;
	if(rt[y]) rt[x]=1,rt[y]=0;
	else ch[pre[y]][ch[pre[y]][1]==y]=x;
	pre[x]=pre[y];
	ch[x][kind]=y;
	pre[y]=x;
	up(y);
}
il void splay(int x) {
	P(x);
	while(!rt[x]) {
		if(rt[pre[x]]) rotate(x,ch[pre[x]][0]==x);
		else {
			rg int y=pre[x];
			rg int kind=ch[pre[y]][0]==y;
			if(ch[y][kind]==x) rotate(x,!kind),rotate(x,kind);
			else rotate(y,kind),rotate(x,kind);
		}
	}
	up(x);
}
il void access(int x) {
	rg int y=0;
	while(x) {
		splay(x);
		if(ch[x][1]) {
			rt[ch[x][1]]=1;
			pre[ch[x][1]]=x;
			chsum[x]+=sum[ch[x][1]];
			chnum[x]+=num[ch[x][1]];
		}
		if(y) rt[y]=0,chsum[x]-=sum[y],chnum[x]-=num[y];
		ch[x][1]=y;
		up(x);
		y=x;
		x=pre[x];
	}
}
il void mroot(int u) {
	access(u);
	splay(u);
	reverse(u);
}
il void Link(int u,int v) {
	mroot(u);
	mroot(v);
	pre[u]=v;
	chnum[v]+=num[u];
	chsum[v]+=sum[u];
	up(v);
}
il void destory(int u,int v) {
	//if(!pd(u,v)) return ;
	mroot(u);
	access(v);
	splay(u);
	pre[v]=0;rt[v]=1;
	ch[u][1]=0;up(u);
	//up(x);
}
int main() {
	//freopen("1.in","r",stdin);
	//freopen("2.out","w",stdout);
	int n,m,k;
	n=read();
	m=read();
	k=read();
	cnt=0;
	tp=0;
	inc(i,1,n) size[++cnt]=1,rt[cnt]=1;
	int u,v,w;
	while(m--) {
		u=read();
		v=read();
		w=read();
		size[++cnt]=1,rt[cnt]=1;
		ke[cnt]=vul[cnt]=w;
		Link(u,cnt);
		Link(v,cnt);
	}
	char str[5];
	while(k--) {
		scanf("%s",str);
		if(str[0]=='L') {
			u=read(),v=read(),w=read(),size[++cnt]=1,rt[cnt]=1;
			ke[cnt]=vul[cnt]=w;
			Link(u,cnt),Link(v,cnt);
		} else if(str[0]=='C') {
			u=read();
			v=read();
			destory(u,v);
		} else if(str[0]=='F') u=read(),mroot(u),key[u]^=1,up(u);
		else u=read(),mroot(u),printf("%lld\n",sum[u]);
	}
	return 0;
}

  

转载于:https://www.cnblogs.com/wang9897/p/8973551.html

你可能感兴趣的:(loj558&loj2011)