NOIP2018:保卫王国(LCT)

传送门

题解:
考场上刚T2导致这道题没写。。。 其实挺傻逼的。

LCT的时候维护一个2*2的矩阵就行了,顺便维护一下虚子树的信息,时间复杂度 O ( n log n ) O(n \log n)

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;

const int RLEN=1<<18|1;
inline char nc() {
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
	char ch=nc(); int i=0,f=1;
	while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
	while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
	return i*f;
}
inline void W(LL x) {
	static int buf[50];
	if(!x) {putchar('0'); return;}
	if(x<0) {putchar('-'); x=-x;}
	while(x) {buf[++buf[0]]=x%10; x/=10;}
	while(buf[0]) putchar(buf[buf[0]--]+'0');
}

const int N=1e5+50;
const LL inf=1e13;
int n,m,pv[N],fa[N];
vector <int> edge[N];

struct mat {
	LL a[2][2];
	mat(LL v=0) {a[0][0]=a[0][1]=a[1][0]=a[1][1]=v;}
	friend inline mat operator *(const mat &a,const mat &b) {
		mat c(inf);
		for(int i=0;i<=1;i++)
			for(int j=0;j<=1;j++)
				for(int k=0;k<=1;k++)
					c.a[i][k]=min(c.a[i][k],a.a[i][j]+b.a[j][k]);
		return c;
	}
};
struct node {
	node *lc,*rc,*fa;
	LL f[2];
	mat a;
	node() : lc(NULL),rc(NULL),fa(NULL) {}
	inline void upt() {
		a.a[1][0]=a.a[1][1]=f[1]; 
		a.a[0][1]=f[0];
		a.a[0][0]=inf;
		if(rc) a=a*rc->a;
		if(lc) a=lc->a*a;
	}
} *pos[N],Pool[N],*pool=Pool;
inline void add(node *x,node *y,int t) {
	LL sg=min(y->a.a[1][0],y->a.a[1][1]);
	LL sf=min(sg,min(y->a.a[0][0],y->a.a[0][1]));
	x->f[0]+=sg*t; x->f[1]+=sf*t;
}
inline void pre(int x,int f) {
	fa[x]=f;
	node *p=pos[x]=++pool;
	p->f[1]=pv[x]; p->f[0]=0;
	for(auto v:edge[x]) 
		if(v^f) pre(v,x);
	p->upt();
	if(f) add(pos[f],p,1), p->fa=pos[f];
}
inline bool isroot(node *x) {return (!x->fa) || (x->fa->lc!=x && x->fa->rc!=x);}
inline bool which(node *x) {return (x->fa->lc)==x;}
inline void rotate(node *x) {
	node *y=x->fa, *z=y->fa;
	if(!isroot(y)) ((z->lc==y) ? z->lc : z->rc)=x;
	y->fa=x; x->fa=z;
	if(y->lc==x) {
		node *b=x->rc;
		if(b) b->fa=y;
		y->lc=b; x->rc=y;
	} else {
		node *b=x->lc;
		if(b) b->fa=y;
		y->rc=b; x->lc=y; 
	} y->upt(); x->upt();
}
inline void splay(node *x) {
	while(!isroot(x)) {
		node *y=x->fa;
		if(!isroot(y)) {
			if(which(x)==which(y)) rotate(y);
			else rotate(x);
		} rotate(x);
	}
}
inline void access(node *x) {
	for(node *y=NULL;x;y=x,x=x->fa) {
		splay(x); 
		if(x->rc) add(x,x->rc,1);
		x->rc=y;
		if(x->rc) add(x,x->rc,-1);
		x->upt();
	}
}
inline void add_lim(int x,int a,LL val) {
	node *p=pos[x];
	access(p); 
	splay(p);
	p->f[a]+=val; p->upt(); 
}

int main() {
	n=rd(), m=rd(); rd();
	for(int i=1;i<=n;i++) pv[i]=rd();
	for(int i=1;i<n;i++) {
		int x=rd(), y=rd();
		edge[x].push_back(y);
		edge[y].push_back(x);
	} pre(1,0);
	for(int i=1;i<=m;i++) {
		int x=rd(), a=rd();
		int y=rd(), b=rd();
		add_lim(x,a^1,inf);
		add_lim(y,b^1,inf);
		splay(pos[1]);
		LL ans=min(pos[1]->a.a[0][0],pos[1]->a.a[0][1]);
		ans=min(ans,min(pos[1]->a.a[1][0],pos[1]->a.a[1][1]));
		add_lim(x,a^1,-inf);
		add_lim(y,b^1,-inf);
		ans=(ans>=inf) ? -1 : ans;
		W(ans), putchar('\n'); 
	}
}
发布了553 篇原创文章 · 获赞 227 · 访问量 24万+

猜你喜欢

转载自blog.csdn.net/qq_35649707/article/details/83989272