社区讨论

萌新妺子没学oi,简单树剖板子过样例但全 WA

P1505[国家集训队] 旅游参与者 3已保存回复 2

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
2 条
当前快照
1 份
快照标识符
@lrln3phf
此快照首次捕获于
2024/01/20 13:39
2 年前
此快照最后确认于
2024/01/20 16:27
2 年前
查看原帖
求调教,悬赏一关注
CPP
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10,INF=2e9+10;
struct Edge
{
	int v,w;
}edge;
struct PII
{
	int x,y;
};
vector<Edge> e[N];
int dep[N],siz[N],son[N],top[N],f[N],a[N];
int dfn[N],idx[N],tot;
int sum[N<<2],tag[N<<2],Max[N<<2],Min[N<<2];
struct PII t[N];	//边对应第几个输入
int n,m;

void dfs_1(int u,int fa)
{
	dep[u] = dep[fa] + 1 , siz[u] = 1 , f[u] = fa;
	for(auto t : e[u])
	{
		if(t.v!=fa)
		{
			dfs_1(t.v,u) , siz[u] += siz[t.v] , a[t.v] = t.w;
			if(siz[son[u]] < siz[t.v])	son[u] = t.v;
		}
	}
}

void dfs_2(int u,int topx)
{
	top[u] = topx , dfn[u] = ++tot , idx[tot] = a[u];
	if(!son[u])		return ;
	dfs_2(son[u],topx);
	for(auto t : e[u])
	{
		if(t.v!=f[u] && t.v!=son[u])
			dfs_2(t.v,t.v);
	}
}


#define mid ((l+r)/2)
#define ls u<<1
#define rs u<<1|1

void pushup(int u)
{
	sum[u] = sum[ls] + sum[rs];

	Min[u] = min(Min[ls] , Min[rs]);

	Max[u] = max(Max[ls] , Max[rs]);
}

void pushdown(int u)
{
	if(!tag[u])		return ;

	tag[ls]^=1 , tag[rs]^=1;

	swap(Max[ls],Min[ls]);
	swap(Max[rs],Min[rs]);

	Max[ls] *= (-1) , Min[ls] *= (-1);
	Max[rs] *= (-1) , Min[rs] *= (-1);

	sum[ls] *= (-1) , sum[rs] *= (-1);

	tag[u] ^= 1;
}

void build(int u,int l,int r)
{
	Min[u] = INF , Max[u] = -INF;
	if(l==r)
	{
		sum[u] = Max[u] = Min[u] =idx[l] ;
		return ;
	}
	build(ls,l,mid) , build(rs,mid+1,r);
	pushup(u);
}

//将区间改为相反数
void change(int u,int l,int r,int ql,int qr)
{
	if(ql<=l && r<=qr)
	{
		tag[u]^=1 , sum[u] *= (-1);
		swap(Min[u],Max[u]);
		Min[u] *= (-1) , Max[u] *= (-1) ;
		return ; 
	}
	pushdown(u);
    if(ql<=mid) 	change(ls,l,mid,ql,qr) ;
    if(mid+1<=qr)   change(rs,mid+1,r,ql,qr);
	pushup(u);
}

void change(int x,int y)
{
	while(top[x]!=top[y])
	{
		if(dep[top[x]] < dep[top[y]])		swap(x,y);
		change(1,1,n,dfn[top[x]],dfn[x]);
		x = f[top[x]];
	}
	if(dep[x] > dep[y])		swap(x,y);
    
	if(x!=y)
		change(1,1,n,dfn[x]+1,dfn[y]);
}

//单点修改
void change_one(int u,int l,int r,int p,int k)
{
	if(l==r)
	{
		sum[u] = Min[u] = Max[u] = k ;
		return ;
	}
	pushdown(u);

	if(p<=mid)		change_one(ls,l,mid,p,k);
	else	change_one(rs,mid+1,r,p,k);

	pushup(u);
}


//询问最大值
int ask_max(int u,int l,int r,int ql,int qr)
{
	if(ql<=l && r<=qr)		return Max[u];

	pushdown(u);

	int s = -INF;

	if(ql<=mid)		s = max(s,ask_max(ls,l,mid,ql,qr));
	if(mid+1<=qr)	s = max(s,ask_max(rs,mid+1,r,ql,qr));

	return s;
}

int ask_max(int x,int y)
{
	int s = -INF;
	while(top[x]!=top[y])
	{
		if(dep[top[x]] < dep[top[y]])		swap(x,y);
		s = max(s,ask_max(1,1,n,dfn[top[x]],dfn[x]));
		x = f[top[x]];
	}
	if(dep[x] > dep[y])		swap(x,y);
	if(x!=y)
		s = max(s,ask_max(1,1,n,dfn[x]+1,dfn[y]));
	return s;
}

//询问最小值
int ask_min(int u,int l,int r,int ql,int qr)
{
	if(ql<=l && r<=qr)		return Min[u];

	pushdown(u);

	int s = INF;

	if(ql<=mid)		s = min(s,ask_min(ls,l,mid,ql,qr));
	if(mid+1<=qr)	s = min(s,ask_min(rs,mid+1,r,ql,qr));

	return s;
}
int ask_min(int x,int y)
{
	int s = INF;
	while(top[x]!=top[y])
	{
		if(dep[top[x]] < dep[top[y]])		swap(x,y);
		s = min(s,ask_min(1,1,n,dfn[top[x]],dfn[x]));
		x = f[top[x]];
	}
	if(dep[x] > dep[y])		swap(x,y);
	if(x!=y)
		s = min(s,ask_min(1,1,n,dfn[x]+1,dfn[y]));
	return s;
}

//询问区间和
int ask_sum(int u,int l,int r,int ql,int qr)
{
	if(ql<=l && r<=qr)		return sum[u];

	pushdown(u);

	int s = 0;

	if(ql<=mid)		s += ask_max(ls,l,mid,ql,qr);
	if(mid+1<=qr)	s += ask_max(rs,mid+1,r,ql,qr);

	return s;
}


int ask_sum(int x,int y)
{
    
	int s = 0;
	while(top[x]!=top[y])
	{
		if(dep[top[x]] < dep[top[y]])		swap(x,y);
		s += ask_sum(1,1,n,dfn[top[x]],dfn[x]);
		x = f[top[x]];
	}
	if(dep[x] > dep[y])		swap(x,y);
	if(x!=y)
		s += ask_sum(1,1,n,dfn[x]+1,dfn[y]);
    
	return s;
}

//询问时记得边的编号+1

#define print   cout << "ok!\n" ;


int main()
{
	ios::sync_with_stdio(false) , cin.tie(0);

	cin>>n;

    

	for(int i=1; i<n; i++)
	{
		int v,u,w;	cin>>u>>v>>w , u++,v++;
		e[u].push_back({v,w}) , e[v].push_back({u,w});
		t[i] = {u,v}; 
	}

	dfs_1(1,0);
	dfs_2(1,1);

	build(1,1,n);

	cin>>m;

	for(int i=1; i<=m; i++)
	{
		string op;	int u,v;
		cin>>op>>u>>v;
        /**/
		if(op=="C")	//单点修改
		{
			int g = dep[t[u].x] > dep[t[u].y]? t[u].x : t[u].y;
			change_one(1,1,n,dfn[g],v);
		}
        else	if(op=="N")		//将区间取反
			change(u+1,v+1); 
		else    if(op=="SUM")	//区间求和
			cout << ask_sum(u+1,v+1) << '\n' ;
		else	if(op=="MAX")	//区间最大
			cout << ask_max(u+1,v+1) << '\n' ;
		else	if(op=="MIN")	//区间最小
			cout << ask_min(u+1,v+1) << '\n' ;  
	}


	return 0;
}

回复

2 条回复,欢迎继续交流。

正在加载回复...