F. Timofey and Black-White Tree

Problem - F - Codeforces

F. Timofey and Black-White Tree_第1张图片

F. Timofey and Black-White Tree_第2张图片

思路:这个题可以用树链剖分做,对于一个新加的黑节点来说,有两种情况,一种是往下走取得最小值,一种是往上走取得最小值,往下走的情况比较简单,就是取所有黑色子节点中的深度的最小值,减去当前节点的深度就是往下走能够取得的最小值,往上走能够取得的最小值假如说另一个点为v,那么最小值一定是d[u]+d[v]-2*d[lca(u,v)],我们能够维护d[v]-2*d[lca(u,v)],那么在查询时,只需要遍历从当前节点往父节点跳的重链,查询出最小的d[v]-2*d[lca(u,v)]即可,而在修改的时候,同样要按照重链往上跳,同时维护一下d[v]-2*d[lca(u,v)]

// Problem: F. Timofey and Black-White Tree
// Contest: Codeforces - Codeforces Round 847 (Div. 3)
// URL: https://codeforces.com/contest/1790/problem/F
// Memory Limit: 256 MB
// Time Limit: 4000 ms

#include
#include
#include
#define fi first
#define se second
#define i128 __int128
using namespace std;
typedef long long ll;
typedef double db;
typedef pair PII;
const double eps=1e-7;
const int N=5e5+7 ,M=5e5+7, INF=0x3f3f3f3f,mod=1e9+7,mod1=998244353;
const long long int llINF=0x3f3f3f3f3f3f3f3f;
inline ll read() {ll x=0,f=1;char c=getchar();while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') {x=(ll)x*10+c-'0';c=getchar();} return x*f;}
inline void write(ll x) {if(x < 0) {putchar('-'); x = -x;}if(x >= 10) write(x / 10);putchar(x % 10 + '0');}
inline void write(ll x,char ch) {write(x);putchar(ch);}
void stin() {freopen("in_put.txt","r",stdin);freopen("my_out_put.txt","w",stdout);}
bool cmp0(int a,int b) {return a>b;}
template T gcd(T a,T b) {return b==0?a:gcd(b,a%b);}
template T lcm(T a,T b) {return a*b/gcd(a,b);}
void hack() {printf("\n----------------------------------\n");}

int T,hackT;
int n,m,k;
int vis[N];
int h[N],e[M],ne[M],idx;
int fa[N],son[N],dep[N],sum[N];
int top[N],id[N],cnt;
int nw[N];
int last[N];

void add(int a,int b) {
	e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

void dfs1(int u,int father,int d) {
	sum[u]=1,dep[u]=d,fa[u]=father;
	
	for(int i=h[u];i!=-1;i=ne[i]) {
		int j=e[i];
		
		if(j==father) continue;
		dfs1(j,u,d+1);
		sum[u]+=sum[j];
		if(sum[son[u]]>1;
		build(u<<1,l,mid),build(u<<1|1,mid+1,r);
		
		pushup(u);
	}
}

void modify_x(int u,int x) {
	if(tr[u].l==x&&tr[u].r==x) {
		tr[u].min1=tr[u].dep;
	}else {
		pushdown(u);
		
		int mid=tr[u].l+tr[u].r>>1;
		if(x<=mid) modify_x(u<<1,x);
		else modify_x(u<<1|1,x);
		
		pushup(u);
	}
}

void modify_l_r(int u,int l,int r,int x) {
	if(tr[u].l>=l&&tr[u].r<=r) {
		tr[u].add=min(tr[u].add,x);
		tr[u].min2=min(tr[u].min2,x-2*tr[u].dep);
	}else {
		pushdown(u);
		
		int mid=tr[u].l+tr[u].r>>1;
		if(l<=mid) modify_l_r(u<<1,l,r,x);
		if(r>mid) modify_l_r(u<<1|1,l,r,x);
		
		pushup(u);
	}
}

int query_1(int u,int l,int r) {
	if(tr[u].l>=l&&tr[u].r<=r) return  tr[u].min1;
	else {
		pushdown(u);
		
		int mid=tr[u].l+tr[u].r>>1;
		int res=INF;
		if(l<=mid) res=min(res,query_1(u<<1,l,r));
		if(r>mid) res=min(res,query_1(u<<1|1,l,r));
		
		return res;
	}
}

int query_2(int u,int l,int r) {
	if(tr[u].l>=l&&tr[u].r<=r) return tr[u].min2;
	else {
		pushdown(u);
		
		int mid=tr[u].l+tr[u].r>>1;
		int res=INF;
		if(l<=mid) res=min(res,query_2(u<<1,l,r));
		if(r>mid) res=min(res,query_2(u<<1|1,l,r));
		
		return res;
	}
}

int qu2(int u) {
	int res=INF;
	while(u!=-1) {
		res=min(res,query_2(1,id[top[u]],id[u]));
		u=fa[top[u]];
	}
	return res;
}

void change2(int u,int temp) {
	while(u!=-1) {
		modify_l_r(1,id[top[u]],id[u],temp);
		u=fa[top[u]];
	}
}

void solve() {
	n=read();
	int co=read();
	
	for(int i=1;i

你可能感兴趣的:(codeforces,算法)