【Codforces】 CF1303G Sum of Prefix Sums

文章讲述了在CF/Luogu方向的一个题目,涉及使用点分治思想和李超树优化求解树上路径的动态规划问题,重点关注sumUP和sumDOWN的计算及查询效率提升。

题目链接

CF方向
Luogu方向

题目解法

其实我第一反应是 d s u    o n    t r e e dsu\;on\;tree dsuontree,但那个不好写,就改写点分治了

树上的静态问题,考虑点分治
考虑一条 u − > l c a − > v u->lca->v u>lca>v 的路径,令 u − > l c a u->lca u>lca 的路径上不包括 l c a lca lca s u m U P = ∑ v a l i ∗ l e n a f t e r    i sumUP=\sum{val_i*len_{after\;i}} sumUP=valilenafteri,总和为 t o t = ∑ v a l i tot=\sum val_i tot=vali l c a − > v lca->v lca>v 的路径上不包括 l c a lca lca s u m D O W N = ∑ v a l i ∗ l e n a f t e r    i sumDOWN=\sum{val_i*len_{after\;i}} sumDOWN=valilenafteri,长度为 l e n len len
考虑这条路径的答案为 s u m U P + t o t ∗ ( l e n + 1 ) + s u m D O W N + v a l l c a ∗ ( l e n + 1 ) sumUP+tot*(len+1)+sumDOWN+val_{lca}*(len+1) sumUP+tot(len+1)+sumDOWN+vallca(len+1)
考虑已知 l c a − > v lca->v lca>v 的路径的信息,问题是如何找到最大的 s u m U P + t o t ∗ ( l e n + 1 ) sumUP+tot*(len+1) sumUP+tot(len+1)
考虑到这是一个一次函数的形式,所以想到李超树维护 k = t o t , b = s u m U P k=tot,b=sumUP k=tot,b=sumUP
这里清空李超树不能全部遍历一遍,需要把用过的清空
注意到整体修改李超树的时间复杂度是 O ( l o g    n ) O(log\;n) O(logn)
点分治自带 O ( n l o g n ) O(nlogn) O(nlogn)
所以时间复杂度为 O ( n l o g 2 n ) O(nlog^2n) O(nlog2n)

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N(150100),inf(1e18);
struct Segment_Tree{
	int mxk[N<<2],mxb[N<<2];
	int calc(int k,int b,int p){
		if(k==-1&&b==-1) return -inf;
		return k*p+b;
	}
	void insert(int l,int r,int x,int k,int b){
		if(calc(k,b,l)<=calc(mxk[x],mxb[x],l)&&calc(k,b,r)<=calc(mxk[x],mxb[x],r)) return;
		if(calc(k,b,l)>calc(mxk[x],mxb[x],l)&&calc(k,b,r)>calc(mxk[x],mxb[x],r)){ mxk[x]=k,mxb[x]=b;return;}
		int mid=(l+r)>>1;
		if(calc(k,b,mid)>calc(mxk[x],mxb[x],mid)) swap(mxk[x],k),swap(mxb[x],b);
		if(mxk[x]>k) insert(l,mid,x<<1,k,b);
		else insert(mid+1,r,x<<1^1,k,b);
	}
	void clear(int l,int r,int x){
		if(mxk[x]==-1&&mxb[x]==-1) return;
		mxk[x]=mxb[x]=-1;
		if(l==r) return;
		int mid=(l+r)>>1;
		clear(l,mid,x<<1),clear(mid+1,r,x<<1^1);
	}
	int query(int l,int r,int x,int p){
		if(l==r) return calc(mxk[x],mxb[x],p);
		int mid=(l+r)>>1,t=calc(mxk[x],mxb[x],p);
		if(mid>=p) return max(t,query(l,mid,x<<1,p));
		else return max(t,query(mid+1,r,x<<1^1,p));
	}
}T;
struct Node{
	int sumUP,sumDOWN,len,tot;
}stk[N];
int top;
int n,val[N],ans;
int e[N<<1],ne[N<<1],h[N],idx;
bool vis[N],cut[N];
inline int read(){
	int FF=0,RR=1;
	char ch=getchar();
	for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
	for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
	return FF*RR;
}
int get_size(int u,int fa){
	int siz=1;
	for(int i=h[u];~i;i=ne[i]) if(!vis[e[i]]&&e[i]!=fa) siz+=get_size(e[i],u);
	return siz;
}
int get_root(int u,int fa,int &rt,int tot){
	if(vis[u]) return 0;
	int siz=1,ms=0;
	for(int i=h[u];~i;i=ne[i]){
		if(e[i]==fa) continue;
		int t=get_root(e[i],u,rt,tot);
		siz+=t,ms=max(ms,t);
	}
	ms=max(ms,tot-siz);
	if(ms<=tot/2) rt=u;
	return siz;
}
void dfs(int u,int fa,int sumUP,int sumDOWN,int tot,int len){
	bool leaf=1;
	for(int i=h[u];~i;i=ne[i]){
		int v=e[i];
		if(v!=fa&&!vis[v]) leaf=0,dfs(v,u,sumUP+val[v]*(len+1),sumDOWN+tot+val[v],tot+val[v],len+1);
	}
	if(leaf) stk[++top]={sumUP,sumDOWN,len,tot};
}
void solve(int rt){
	get_root(rt,-1,rt,get_size(rt,-1));
	vis[rt]=1;
	top=0;
	for(int i=h[rt];~i;i=ne[i]) if(!vis[e[i]]){ dfs(e[i],rt,val[e[i]],val[e[i]],val[e[i]],1);cut[top]=1;}
	T.clear(1,n,1);
//	cout<<rt<<'\n';
//	for(int i=1;i<=top;i++) cout<<stk[i].len<<' '<<stk[i].sumDOWN<<' '<<stk[i].sumUP<<' '<<stk[i].tot<<'\n';
//	cout<<'\n';
	for(int i=1;i<=top;i++) ans=max(ans,max(stk[i].sumUP+stk[i].tot+val[rt],stk[i].sumDOWN+val[rt]*(stk[i].len+1)));
	for(int i=1;i<=top;){
		int j=i;
		while(!cut[j]) ans=max(ans,T.query(1,n,1,stk[j].len+1)+stk[j].sumDOWN+val[rt]*(stk[j].len+1)),j++;
		ans=max(ans,T.query(1,n,1,stk[j].len+1)+stk[j].sumDOWN+val[rt]*(stk[j].len+1));
		while(!cut[i]) T.insert(1,n,1,stk[i].tot,stk[i].sumUP),i++;
		T.insert(1,n,1,stk[i].tot,stk[i].sumUP),i++;
	}
	T.clear(1,n,1);
	for(int i=top;i>=1;){
		ans=max(ans,T.query(1,n,1,stk[i].len+1)+stk[i].sumDOWN+val[rt]*(stk[i].len+1));
		int j=i-1;
		while(j&&!cut[j]) ans=max(ans,T.query(1,n,1,stk[j].len+1)+stk[j].sumDOWN+val[rt]*(stk[j].len+1)),j--;
		T.insert(1,n,1,stk[i].tot,stk[i].sumUP);i--;
		while(i&&!cut[i]) T.insert(1,n,1,stk[i].tot,stk[i].sumUP),i--;
	}
	for(int i=1;i<=top;i++) cut[i]=0;
	for(int i=h[rt];~i;i=ne[i]) if(!vis[e[i]]) solve(e[i]);
}
void add(int x,int y){ e[idx]=y,ne[idx]=h[x],h[x]=idx++;}
signed main(){
	n=read();
	memset(h,-1,sizeof(h));
	for(int i=1;i<n;i++){
		int x=read(),y=read();
		add(x,y),add(y,x);
	}
	for(int i=1;i<=n;i++) val[i]=read();
	T.clear(1,n,1);
	solve(1);
	printf("%lld",ans);
	return 0;
}

F. Attraction Theory time limit per test2 seconds memory limit per test256 megabytes Taylor Swift - Love Story (Taylor's Version) ⠀ There are 𝑛 people in positions 𝑝1,𝑝2,…,𝑝𝑛 on a one-dimensional coordinate axis. Initially, 𝑝𝑖=𝑖 for each 1≤𝑖≤𝑛. You can introduce an attraction at some integer coordinate 𝑥 (1≤𝑥≤𝑛), and then all the people will move closer to the attraction to look at it. Formally, if you put an attraction in position 𝑥 (1≤𝑥≤𝑛), the following changes happen for each person 𝑖 (1≤𝑖≤𝑛): if 𝑝𝑖=𝑥, no change; if 𝑝𝑖<𝑥, the person moves in the positive direction, and 𝑝𝑖 is incremented by 1; if 𝑝𝑖>𝑥, the person moves in the negative direction, and 𝑝𝑖 is decremented by 1. You can put attractions any finite number of times, and in any order you want. It can be proven that all positions of a person always stays within the range [1,𝑛], i.e. 1≤𝑝𝑖≤𝑛 at all times. Each position 𝑥 (1≤𝑥≤𝑛), has a value 𝑎𝑥 associated with it. The score of a position array [𝑝1,𝑝2,…,𝑝𝑛], denoted by 𝑠𝑐𝑜𝑟𝑒(𝑝), is &sum;𝑛𝑖=1𝑎𝑝𝑖, i.e. your score increases by 𝑎𝑥 for every person standing at 𝑥 in the end. Over all possible distinct position arrays 𝑝 that are possible with placing attractions, find the sum of 𝑠𝑐𝑜𝑟𝑒(𝑝). Since the answer may be large, print it modulo 998244353. Input Each test contains multiple test cases. The first line contains the number of test cases 𝑡 (1≤𝑡≤104). The description of the test cases follows. The first line of each test case contains a single integer 𝑛 (1≤𝑛≤2⋅105). The second line of each test case contains 𝑛 integers — 𝑎1,𝑎2,…,𝑎𝑛 (1≤𝑎𝑖≤109) It is guaranteed that the sum of 𝑛 over all test cases does not exceed 2⋅105. Output For each test case, output a single line containing an integer: the sum of 𝑠𝑐𝑜𝑟𝑒(𝑝) over all possible distinct position arrays 𝑝 that are possible with placing attractions, modulo 998244353. Example inputCopy 7 1 1 2 5 10 3 1 1 1 4 1 1 1 1 4 10 2 9 7 5 1000000000 1000000000 1000000000 1000000000 1000000000 8 100 2 34 59 34 27 5 6 outputCopy 1 45 24 72 480 333572930 69365 Note In the first test case, the only possible result is that person 1 stays at 1. The score of that is 𝑎1=1. In the second test case, the following position arrays [𝑝1,𝑝2] are possible: [1,2], score 15; [1,1], score 10; [2,2], score 20. The sum of scores is 15+10+20=45. In the third test case, the following position arrays [𝑝1,𝑝2,𝑝3] are possible: [1,1,1]; [1,1,2]; [1,2,2]; [1,2,3]; [2,2,2]; [2,2,3]; [2,3,3]; [3,3,3]. Each has a score of 3, and thus the total sum is 24.解决这道题,用c++
09-25
Index of (root) / releases / 24.10.1 / targets / x86 / 64 / Image Files These are the image files for the x86/64 target. Check that the sha256sum of the file you downloaded matches the sha256sum below. Shortened image file names below have the same prefix: openwrt-24.10.1-x86-64-... Image for your Device sha256sum File Size Date generic-ext4-combined-efi.img.gz a312646e30737891e86b45823cf109bd73eb71194d85e05039d139732af7b496 13496.1 KB Mon Apr 14 09:56:55 2025 generic-ext4-combined.img.gz 924e4b83a34d600914841d53df51bba930d4a56070032a30cba5bca87273c213 13306.3 KB Mon Apr 14 09:56:55 2025 generic-ext4-rootfs.img.gz c1d2ce92a62c14e7b8764db61603b7eca29811ce4ade9b375daafdb19589e66a 7309.2 KB Mon Apr 14 09:56:49 2025 generic-kernel.bin 297c9086f7d1e5b2176a1bbd5155b66d15e62cef523d4d4c64e94988f93b9f52 5605.0 KB Mon Apr 14 09:56:16 2025 generic-squashfs-combined-efi.img.gz c669557e31324bb81842d2f154c5e85a9c99491db823b9ac320eab2c169dc425 12090.4 KB Mon Apr 14 09:56:51 2025 generic-squashfs-combined.img.gz 72d6776db565e1707d72566289c111d57984ad5d75a4065f025a7caef1e34b17 11899.3 KB Mon Apr 14 09:56:49 2025 generic-squashfs-rootfs.img.gz 7eb7325d8b6f0a50c94e5bfd10b39d7a6b396e711b510211a24f16eac5342e52 5902.6 KB Mon Apr 14 09:56:49 2025 rootfs.tar.gz bc861d4fbad1ad034963d47dd070cfe638918c87865cda617ec01f222b1cb5fe 4475.9 KB Mon Apr 14 09:56:19 2025 Supplementary Files These are supplementary resources for the x86/64 target. They include build tools, the imagebuilder, sha256sum, GPG signature file, and other useful files. Filename sha256sum File Size Date kmods/ - - Mon Apr 14 10:04:09 2025 packages/ - - Mon Apr 14 10:04:03 2025 config.buildinfo 50aca2f8524c0fffff683447b362154e2317563452700f27487ef53a2592dd0a 1.9 KB Mon Apr 14 10:01:43 2025 feeds.buildinfo 83eac85e59cf2286f154027a8245893446a5e0e07a7fd3ee8bb9fdcd006a4caa 0.4 KB Mon Apr 14 10:01:43 2025 kernel-debug.tar.zst 1f1111b931532a76a79726c916fc39b316b0d2532b0474d988e245e481a3098e 124202.5 KB Mon Apr 14 09:56:16 2025 llvm-bpf-18.1.7.Linux-x86_64.tar.zst 41b6aac8654914e0571a160ab585c488865415a510f131ae964cf7b7b0d6a2cf 45836.6 KB Mon Apr 14 09:57:43 2025 openwrt-24.10.1-x86-64.bom.cdx.json a96e9e94d8bcf94441dfdf9aa02483ee39a2d477bf296b0303fdfc23c3b379c3 15.6 KB Mon Apr 14 09:56:56 2025 openwrt-24.10.1-x86-64.manifest fdf1770cb475777fd255b01252fa61a51af2eb05673ddad3d8ed56b1ba0e7d44 3.8 KB Mon Apr 14 09:56:55 2025 openwrt-imagebuilder-24.10.1-x86-64.Linux-x86_64.tar.zst 8a5c461d56126a1f46a444570b03e528425c1d4610981fe4e74ef29dde1807f2 42994.0 KB Mon Apr 14 09:59:29 2025 openwrt-sdk-24.10.1-x86-64_gcc-13.3.0_musl.Linux-x86_64.tar.zst ff013b90ea4912c2c9fd55aef6b399fedf2bb3e1d702a3e62ef17afcafdab221 252836.1 KB Mon Apr 14 10:01:08 2025 openwrt-toolchain-24.10.1-x86-64_gcc-13.3.0_musl.Linux-x86_64.tar.zst a229b472b6fae195a0e206bc4fc8802602df8e732b795fd975dd7c1d2c72e4d4 68575.0 KB Mon Apr 14 09:57:41 2025 profiles.json 4fd1f276f127107d675f614bc2dcdb5c3731c0e9e4046b8e984d11ef5fb9ad72 2.5 KB Mon Apr 14 10:02:09 2025 sha256sums - 181.7 KB Mon Apr 14 10:03:53 2025 sha256sums.asc - 0.3 KB Mon Apr 14 10:04:03 2025 sha256sums.sig - 0.1 KB Mon Apr 14 10:04:03 2025 version.buildinfo 919c1b2077f9a6c309432bcd519d3f6fb658d12363afafa5f2cf80823de43dd2 0.0 KB
08-14
由于没有提供 example1、example2、example3、example4、example5 函数的具体代码,下面以引用中的代码为例进行分析: ### `another_example_function` 函数 - **功能**:该函数接收一个整数参数 `n`,创建一个长度为 `n` 且元素都为 0 的列表,并将其返回。 ```python def another_example_function(n): my_list = [0] * n return my_list # 调用函数 result = another_example_function(10) print(result) ``` - **复杂度**: - **时间复杂度**:创建列表 `[0] * n` 的时间复杂度为 $O(n)$,因为需要初始化 `n` 个元素。 - **空间复杂度**:返回的列表需要 $O(n)$ 的额外空间。 - **优化建议**:此函数已经较为简洁,在功能上没有明显的优化空间。如果需要频繁创建这样的列表,可考虑使用生成器表达式或迭代器来减少内存占用。 ### `my_function` 函数 - **功能**:该函数创建一个空列表 `result`,然后使用 `for` 循环计算 0 到 99999 的平方,并将结果添加到 `result` 列表中,最后返回该列表。 ```python import cProfile def my_function(): # 这里是你的代码 result = [] for i in range(100000): result.append(i ** 2) return result # 运行性能分析 cProfile.run('my_function()') ``` - **复杂度**: - **时间复杂度**:`for` 循环执行 100000 次,每次循环中计算平方和 `append` 操作的时间复杂度为 $O(1)$,因此总的时间复杂度为 $O(n)$,其中 $n = 100000$。 - **空间复杂度**:返回的列表需要 $O(n)$ 的额外空间。 - **优化建议**: - 可以使用生成器表达式来减少内存占用,避免一次性创建整个列表。 ```python import cProfile def my_function(): return (i ** 2 for i in range(100000)) # 运行性能分析 cProfile.run('list(my_function())') ``` ### 复杂度评估与优化工具 - **复杂度评估**:可以使用 Radon 工具评估代码的复杂度,例如使用 `mi` 命令获取代码的维护指数,并查看是否有重复代码:`radon mi --statistics example.py` [^4]。 - **性能分析**:使用 Python 内置的性能分析工具,如 `cProfile` 和 `line_profiler`,帮助识别代码中最耗时的部分 [^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值