BZOJ P4127 Abs 做题记录(附本题对拍代码)

前置芝士:树剖,势能分析。

题目大意

给你一颗 \(n\) 个节点的有点权的树,你需要支持路径上所有点加 \(d(d\ge 0)\) 和查询路径上所有点的绝对值之和。

思路

首先我们知道一个区间的绝对值之和等于一个区间的正数之和乘以 \(2\) 减去区间和。

然后我们发现 \(d\ge 0\),这意味着我们所有点的点权只会变大,那么每个点从负数变为正数最多只会有一次。我们对于每个从负数变为正数的时刻,在线段树上暴力修改,他的均摊复杂度为 \(O(n\log n)\),同时维护我们要的区间和和区间正数和。

我们要怎么知道哪个时刻有东西从负数变为正数呢?我们不妨再维护一个负数的最大值 \(nmax\),在区间加 \(val\) 的时候,如果当前区间满足 \(nmax+val<0\),那么不会有任何数变成正数,直接修改并打标记就好了,否则就需要向下修改。

时间复杂度:\(O(n\log n)\)

点击查看代码

文件名:P4127.cpp

#include<bits/stdc++.h>

#define int ll
#define pii pair<int,int> 
#define pll pair<long long,long long> 
#define ll long long
#define i128 __int128

#define mem(a,b) memset((a),(b),sizeof(a))
#define m0(a) memset((a),0,sizeof(a))
#define m1(a) memset(a,-1,sizeof(a))
#define lb(x) ((x)&-(x))
#define lc(x) ((x)<<1)
#define rc(x) (((x)<<1)|1)
#define pb(G,x) (G).push_back((x))
#define For(a,b,c) for(int a=(b);a<=(c);a++)
#define Rep(a,b,c) for(int a=(b);a>=(c);a--)
#define in1(a) a=read()
#define in2(a,b) a=read(), b=read()
#define in3(a,b,c) a=read(), b=read(), c=read()
#define in4(a,b,c,d) a=read(), b=read(), c=read(), d=read()
#define fst first 
#define scd second 
#define dbg puts("IAKIOI")

using namespace std;

int read() {
	int x=0,f=1; char c=getchar();
	for(;c<'0'||c>'9';c=getchar()) f=(c=='-'?-1:1); 
	for(;c<='9'&&c>='0';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
	return x*f;
}
void write(int x) { if(x>=10) write(x/10); putchar('0'+x%10); }

const int mod = 998244353;
int qpo(int a,int b) {int res=1; for(;b;b>>=1,a=(a*a)%mod) if(b&1) res=res*a%mod; return res; }
int inv(int a) {return qpo(a,mod-2); }

#define maxn 100050

int n,m,a[maxn];
vector<int> G[maxn];
struct pt {
	int dep,fa,siz,mxs,dfn,top;
}tr[maxn]; int dfncnt,dfna[maxn];

void dfs1(int u,int fa) {
	tr[u].siz=1,tr[u].fa=fa,tr[u].dep=tr[fa].dep+1;
	for(auto v:G[u]) if(v!=fa) {
		dfs1(v,u); tr[u].siz+=tr[v].siz;
		if(tr[v].siz>tr[tr[u].mxs].siz) tr[u].mxs=v;
	}
}

void dfs2(int u,int top) {
	tr[u].dfn=++dfncnt; tr[u].top=top; dfna[dfncnt]=a[u];
	if(tr[u].mxs) dfs2(tr[u].mxs,top);
	for(auto v:G[u]) if(v!=tr[u].fa&&v!=tr[u].mxs) dfs2(v,v);
}

struct SegT {
	struct node {
		int sum,psum,nflg,nmax,tag,cnt;
	}tr[maxn<<2];
	
	void psd(int idx,int l,int r) {
		if(tr[idx].tag==0) return ;
		int mid=l+r>>1;
		tr[lc(idx)].tag+=tr[idx].tag;
		tr[rc(idx)].tag+=tr[idx].tag;
		tr[lc(idx)].sum+=tr[idx].tag*(mid-l+1);
		tr[rc(idx)].sum+=tr[idx].tag*(r-mid);
		if(tr[lc(idx)].nflg) tr[lc(idx)].nmax+=tr[idx].tag;
		if(tr[rc(idx)].nflg) tr[rc(idx)].nmax+=tr[idx].tag;
		tr[lc(idx)].psum+=tr[idx].tag*(mid-l+1-tr[lc(idx)].cnt);
		tr[rc(idx)].psum+=tr[idx].tag*(r-mid-tr[rc(idx)].cnt);
		tr[idx].tag=0;
	}
	void psu(int idx) {
		tr[idx].sum=tr[lc(idx)].sum+tr[rc(idx)].sum;
		tr[idx].psum=tr[lc(idx)].psum+tr[rc(idx)].psum;
		tr[idx].nflg=tr[lc(idx)].nflg|tr[rc(idx)].nflg;
		tr[idx].cnt=tr[lc(idx)].cnt+tr[rc(idx)].cnt;
		tr[idx].nmax=max((tr[lc(idx)].nflg?tr[lc(idx)].nmax:-1e18),(tr[rc(idx)].nflg?tr[rc(idx)].nmax:-1e18));
	}
	
	void build(int idx,int l,int r,int a[]) {
		tr[idx].tag=0;
		if(l==r) {
			tr[idx].sum=a[l];
			if(a[l]>=0) tr[idx].psum=a[l],tr[idx].nflg=0,tr[idx].nmax=-1e18,tr[idx].cnt=0;
			else tr[idx].nflg=1,tr[idx].nmax=a[l],tr[idx].psum=0,tr[idx].cnt=1;
//			cout<<idx<<' '<<l<<' '<<r<<' '<<tr[idx].sum<<' '<<tr[idx].psum<<' '<<tr[idx].nflg<<' '<<tr[idx].nmax<<' '<<tr[idx].cnt<<'\n';
			return ;
		}
		int mid=l+r>>1;
		build(lc(idx),l,mid,a);
		build(rc(idx),mid+1,r,a);
		psu(idx);
//		cout<<idx<<' '<<l<<' '<<r<<' '<<tr[idx].sum<<' '<<tr[idx].psum<<' '<<tr[idx].nflg<<' '<<tr[idx].nmax<<' '<<tr[idx].cnt<<'\n';
	}
	void modi(int idx,int l,int r,int L,int R,int val) {
//		cout<<"BEFORE:"<<idx<<' '<<l<<' '<<r<<' '<<L<<' '<<R<<' '<<val<<' '<<tr[idx].tag<<' '<<tr[idx].sum<<' '<<tr[idx].psum<<' '<<tr[idx].nflg<<' '<<tr[idx].nmax<<' '<<tr[idx].cnt<<'\n';
		if(L<=l&&r<=R&&(tr[idx].nflg==0||tr[idx].nmax+val<0)) {
			tr[idx].tag+=val; if(tr[idx].nflg) tr[idx].nmax+=val;
			tr[idx].sum+=val*(r-l+1),tr[idx].psum+=val*(r-l+1-tr[idx].cnt);
//			cout<<"AFTER1:"<<idx<<' '<<l<<' '<<r<<' '<<L<<' '<<R<<' '<<tr[idx].tag<<' '<<tr[idx].sum<<' '<<tr[idx].psum<<' '<<tr[idx].nflg<<' '<<tr[idx].nmax<<' '<<tr[idx].cnt<<'\n';
			return ;
		}
		if(l==r) {
			tr[idx].sum+=val;
			if(tr[idx].sum>=0) tr[idx].nflg=0,tr[idx].psum=tr[idx].sum,tr[idx].nmax=-1e18,tr[idx].cnt=0;
			else tr[idx].nmax+=val;
//			cout<<"AFTER2:"<<idx<<' '<<l<<' '<<r<<' '<<L<<' '<<R<<' '<<tr[idx].tag<<' '<<tr[idx].sum<<' '<<tr[idx].psum<<' '<<tr[idx].nflg<<' '<<tr[idx].nmax<<' '<<tr[idx].cnt<<'\n';
			return ;
		}
		psd(idx,l,r);
		int mid=l+r>>1;
		if(L<=mid) modi(lc(idx),l,mid,L,R,val);
		if(R>mid) modi(rc(idx),mid+1,r,L,R,val);
		psu(idx);
//		cout<<"AFTER3:"<<idx<<' '<<l<<' '<<r<<' '<<L<<' '<<R<<' '<<tr[idx].tag<<' '<<tr[idx].sum<<' '<<tr[idx].psum<<' '<<tr[idx].nflg<<' '<<tr[idx].nmax<<' '<<tr[idx].cnt<<'\n';
	}
	int query(int idx,int l,int r,int L,int R) {
//		cout<<idx<<' '<<l<<' '<<r<<' '<<L<<' '<<R<<' '<<tr[idx].tag<<' '<<tr[idx].sum<<' '<<tr[idx].psum<<' '<<tr[idx].nflg<<' '<<tr[idx].nmax<<' '<<tr[idx].cnt<<'\n';
		if(L<=l&&r<=R) return tr[idx].psum*2-tr[idx].sum;
		psd(idx,l,r);
		int mid=l+r>>1,res=0;
		if(L<=mid) res=query(lc(idx),l,mid,L,R);
		if(R>mid) res+=query(rc(idx),mid+1,r,L,R);
		return res;
	}
}Tr;

void modiL(int x,int y,int val) {
	while(tr[x].top!=tr[y].top) {
		if(tr[tr[x].top].dep<tr[tr[y].top].dep) swap(x,y);
		Tr.modi(1,1,n,tr[tr[x].top].dfn,tr[x].dfn,val);
		x=tr[tr[x].top].fa;
	}
	if(tr[x].dep>tr[y].dep) swap(x,y);
	Tr.modi(1,1,n,tr[x].dfn,tr[y].dfn,val);
}

int queryL(int x,int y) {
	int res=0;
	while(tr[x].top!=tr[y].top) {
		if(tr[tr[x].top].dep<tr[tr[y].top].dep) swap(x,y);
		res+=Tr.query(1,1,n,tr[tr[x].top].dfn,tr[x].dfn);
		x=tr[tr[x].top].fa;
	}
	if(tr[x].dep>tr[y].dep) swap(x,y);
	res+=Tr.query(1,1,n,tr[x].dfn,tr[y].dfn);
	return res;
}

void work() {
	in2(n,m);
	For(i,1,n) in1(a[i]);
	For(i,2,n) {
		int u,v; in2(u,v);
		G[u].push_back(v),G[v].push_back(u);
	}
	dfs1(1,1),dfs2(1,1);
	Tr.build(1,1,n,dfna);
//	For(i,1,n) cout<<i<<' '<<tr[i].dfn<<' '<<a[i]<<'\n';
	while(m--) {
		int opt,x,y,z;
		in3(opt,x,y);
//		puts("---");
		if(opt==1) {
			in1(z);
			modiL(x,y,z);
		} else {
			cout<<queryL(x,y)<<'\n';
		}
//		puts("---");
	}
}

signed main() {
//	freopen("data.in","r",stdin);
//	freopen("myans.out","w",stdout);
//	ios::sync_with_stdio(false); 
//	cin.tie(0); cout.tie(0);
	double stt=clock();
	int _=1;
//	_=read();
//	cin>>_;
	For(i,1,_) {
		work();
	}
	cerr<<"\nTotal Time is:"<<(clock()-stt)*1.0/1000<<" second(s)."<<'\n';
	return 0;
}
其他的对拍代码

暴力(文件名 baoli.cpp

#include<bits/stdc++.h>

#define int ll
#define pii pair<int,int> 
#define pll pair<long long,long long> 
#define ll long long
#define i128 __int128

#define mem(a,b) memset((a),(b),sizeof(a))
#define m0(a) memset((a),0,sizeof(a))
#define m1(a) memset(a,-1,sizeof(a))
#define lb(x) ((x)&-(x))
#define lc(x) ((x)<<1)
#define rc(x) (((x)<<1)|1)
#define pb(G,x) (G).push_back((x))
#define For(a,b,c) for(int a=(b);a<=(c);a++)
#define Rep(a,b,c) for(int a=(b);a>=(c);a--)
#define in1(a) a=read()
#define in2(a,b) a=read(), b=read()
#define in3(a,b,c) a=read(), b=read(), c=read()
#define in4(a,b,c,d) a=read(), b=read(), c=read(), d=read()
#define fst first 
#define scd second 
#define dbg puts("IAKIOI")

using namespace std;

int read() {
	int x=0,f=1; char c=getchar();
	for(;c<'0'||c>'9';c=getchar()) f=(c=='-'?-1:1); 
	for(;c<='9'&&c>='0';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
	return x*f;
}
void write(int x) { if(x>=10) write(x/10); putchar('0'+x%10); }

const int mod = 998244353;
int qpo(int a,int b) {int res=1; for(;b;b>>=1,a=(a*a)%mod) if(b&1) res=res*a%mod; return res; }
int inv(int a) {return qpo(a,mod-2); }

#define maxn 200050

int n,m;
int a[maxn];
vector<int> G[maxn];
int fa[maxn],dep[maxn];

void dfs(int u,int f) {
	fa[u]=f,dep[u]=dep[f]+1;
	for(auto v:G[u]) if(v!=f) dfs(v,u);
}

void add(int x,int y,int val) {
	while(x!=y) {
		if(dep[x]<dep[y]) swap(x,y);
		a[x]+=val;
		x=fa[x];
	}
	a[x]+=val;
	return ;
}

int query(int x,int y) {
	int res=0;
	while(x!=y) {
		if(dep[x]<dep[y]) swap(x,y);
		res+=abs(a[x]);
		x=fa[x];
	}
	return res+abs(a[x]);
}

void work() {
	in2(n,m);
	For(i,1,n) in1(a[i]);
	For(i,2,n) {
		int u,v; in2(u,v);
		G[u].push_back(v),G[v].push_back(u);
	}
	dfs(1,1);
	For(i,1,m) {
		int opt,x,y,z;
		in3(opt,x,y);
		if(opt==1) {
			in1(z);
			add(x,y,z);
		} else {
			cout<<query(x,y)<<'\n';
		}
	}
}

signed main() {
	freopen("data.in","r",stdin);
	freopen("ans.out","w",stdout);
//	ios::sync_with_stdio(false); 
//	cin.tie(0); cout.tie(0);
	double stt=clock();
	int _=1;
//	_=read();
//	cin>>_;
	For(i,1,_) {
		work();
	}
	cerr<<"\nTotal Time is:"<<(clock()-stt)*1.0/1000<<" second(s)."<<'\n';
	return 0;
}

数据生成器(文件名:gen.cpp

#include<bits/stdc++.h>

#define pii pair<int,int> 
#define pll pair<long long,long long> 
#define ll long long
#define i128 __int128

#define mem(a,b) memset((a),(b),sizeof(a))
#define m0(a) memset((a),0,sizeof(a))
#define m1(a) memset(a,-1,sizeof(a))
#define lb(x) ((x)&-(x))
#define lc(x) ((x)<<1)
#define rc(x) (((x)<<1)|1)
#define pb(G,x) (G).push_back((x))
#define For(a,b,c) for(int a=(b);a<=(c);a++)
#define Rep(a,b,c) for(int a=(b);a>=(c);a--)
#define in1(a) a=read()
#define in2(a,b) a=read(), b=read()
#define in3(a,b,c) a=read(), b=read(), c=read()
#define in4(a,b,c,d) a=read(), b=read(), c=read(), d=read()
#define fst first 
#define scd second 
#define dbg puts("IAKIOI")

using namespace std;

int read() {
	int x=0,f=1; char c=getchar();
	for(;c<'0'||c>'9';c=getchar()) f=(c=='-'?-1:1); 
	for(;c<='9'&&c>='0';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
	return x*f;
}
void write(int x) { if(x>=10) write(x/10); putchar('0'+x%10); }

const int mod = 998244353;
int qpo(int a,int b) {int res=1; for(;b;b>>=1,a=(a*a)%mod) if(b&1) res=res*a%mod; return res; }
int inv(int a) {return qpo(a,mod-2); }

#define maxn 200050

mt19937 myrnd(time(NULL));

int n,m;
int a[maxn];

int u[maxn],v[maxn];

int rnd(int l,int r) {
	return (l+abs((int)myrnd())%(r-l+1));
}

void work() {
	n=5,m=5;
	cout<<n<<' '<<m<<'\n';
	For(i,1,n) a[i]=rnd(-10,10),cout<<a[i]<<' '; puts("");
	For(i,2,n) {
		u[i]=i,v[i]=rnd(1,i-1);
		cout<<u[i]<<' '<<v[i]<<'\n';
	}
	For(i,1,m) {
		int opt=rnd(1,2),u=rnd(1,n),v=rnd(1,n);
		cout<<opt<<' ';
		if(opt==1) {
			int d=rnd(0,10);
			cout<<u<<' '<<v<<' '<<d<<'\n';
		} else {
			cout<<u<<' '<<v<<'\n';
		}
	}
}

signed main() {
//	freopen("data.in","r",stdin);
	freopen("data.in","w",stdout);
//	ios::sync_with_stdio(false); 
//	cin.tie(0); cout.tie(0);
	double stt=clock();
	int _=1;
//	_=read();
//	cin>>_;
	For(i,1,_) {
		work();
	}
	cerr<<"\nTotal Time is:"<<(clock()-stt)*1.0/1000<<" second(s)."<<'\n';
	return 0;
}

对拍程序(文件名:pai.cpp

#include<bits/stdc++.h>

#define pii pair<int,int> 
#define pll pair<long long,long long> 
#define ll long long
#define i128 __int128

#define mem(a,b) memset((a),(b),sizeof(a))
#define m0(a) memset((a),0,sizeof(a))
#define m1(a) memset(a,-1,sizeof(a))
#define lb(x) ((x)&-(x))
#define lc(x) ((x)<<1)
#define rc(x) (((x)<<1)|1)
#define pb(G,x) (G).push_back((x))
#define For(a,b,c) for(int a=(b);a<=(c);a++)
#define Rep(a,b,c) for(int a=(b);a>=(c);a--)
#define in1(a) a=read()
#define in2(a,b) a=read(), b=read()
#define in3(a,b,c) a=read(), b=read(), c=read()
#define in4(a,b,c,d) a=read(), b=read(), c=read(), d=read()
#define fst first 
#define scd second 
#define dbg puts("IAKIOI")

using namespace std;

int read() {
	int x=0,f=1; char c=getchar();
	for(;c<'0'||c>'9';c=getchar()) f=(c=='-'?-1:1); 
	for(;c<='9'&&c>='0';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
	return x*f;
}
void write(int x) { if(x>=10) write(x/10); putchar('0'+x%10); }

const int mod = 998244353;
int qpo(int a,int b) {int res=1; for(;b;b>>=1,a=(a*a)%mod) if(b&1) res=res*a%mod; return res; }
int inv(int a) {return qpo(a,mod-2); }

#define maxn 200050

void work() {
	int cnt=0;
	while(1) {
		system("gen.exe");
		system("baoli.exe");
		system("P4127.exe");
		if(system("fc ans.out myans.out")) {
			cout<<"WA!";
			return ;
			
		} else {
			cout<<"AC! #Case:"<<++cnt<<'\n';
		}
	}
}

signed main() {
//	freopen("data.in","r",stdin);
//	freopen("myans.out","w",stdout);
//	ios::sync_with_stdio(false); 
//	cin.tie(0); cout.tie(0);
	double stt=clock();
	int _=1;
//	_=read();
//	cin>>_;
	For(i,1,_) {
		work();
	}
	cerr<<"\nTotal Time is:"<<(clock()-stt)*1.0/1000<<" second(s)."<<'\n';
	return 0;
}
posted @ 2025-08-21 10:51  coding_goat_qwq  阅读(11)  评论(0)    收藏  举报