• #树链剖分,背包#洛谷 5391 [Cnoi2019]青染之心


    题目

    Cirno初始有一个空的物品序列,一个大小为 (V) 的背包,现在你有 (q) 个操作,分为两种:

    add (x) (y) : 表示加入一种体积为 (x), 价值为 (y) 的物品到序列末尾
    erase : 表示删除序列末尾的物品
    对于每个操作结束以后,你需要求出 :

    假设序列中的每种物品都有无穷多个,Cirno的背包可以装下的物品最大价值和。

    (q,vleq 2*10^4)


    分析

    即使5s的限制,线段树分治也会超时
    考虑删除实际上就是回溯到上一个版本,那么可以按照这样建一棵关系树,
    直接按照这棵关系树跑就可以做到时间复杂度严格(O(qv)),但是会MLE,
    考虑树链剖分的一个性质,一个点到根节点不会经过超过(log)条轻边,
    则只需要保留重儿子信息即可,空间复杂度(O(vlog_2q))


    代码

    #include <cstdio>
    #include <cctype>
    #define rr register
    using namespace std;
    const int N=20011; struct node{int y,next;}e[N];
    int siz[N],big[N],dp[15][N],ans[N],as[N],et,rk[N],w[N],c[N],Q,m,n,Top,stac[N];
    inline signed iut(){
    	rr int ans=0; rr char c=getchar();
    	while (!isdigit(c)) c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans;
    }
    inline void print(int ans){
    	if (ans>9) print(ans/10);
    	putchar(ans%10+48);
    }
    inline signed max(int a,int b){return a>b?a:b;}
    inline void dfs1(int x){
    	siz[x]=1;
    	for (rr int i=as[x],SIZ=-1;i;i=e[i].next){
    	    dfs1(e[i].y),siz[x]+=siz[e[i].y];
    		if (SIZ<siz[e[i].y]) SIZ=siz[e[i].y],big[x]=e[i].y;	
    	}
    }
    inline void dfs2(int x,int d,int las){
    	for (rr int i=0;i<w[x];++i) dp[d][i]=dp[las][i];
    	for (rr int i=w[x];i<=m;++i) dp[d][i]=max(dp[las][i],dp[d][i-w[x]]+c[x]);
    	ans[x]=dp[d][m];
    	for (rr int i=as[x];i;i=e[i].next)
    	    if (e[i].y!=big[x]) dfs2(e[i].y,d+1,d);
    	if (big[x]) dfs2(big[x],d,d);
    }
    signed main(){
    	Q=iut(),m=iut();
    	for (rr int i=1;i<=Q;++i){
    		rr char ch=getchar();
    		while (ch!='a'&&ch!='e') ch=getchar();
    		if (ch=='e') --Top,getchar(),getchar(),getchar(),getchar();
    		else {
    			w[++n]=iut(),c[n]=iut();
    			if (stac[Top]) e[++et]=(node){n,as[stac[Top]]},as[stac[Top]]=et;
    			stac[++Top]=n;
    		}
    		if (Top) rk[i]=stac[Top];
    	}
    	for (rr int i=1;i<=n;++i)
    	    if (!siz[i]) dfs1(i),dfs2(i,1,0);
    	for (rr int i=1;i<=Q;++i) print(ans[rk[i]]),putchar(10);
    	return 0;
    } 
    
  • 相关阅读:
    sql语句
    数据结构
    Collection接口
    【学习笔记】〖九度OJ〗题目1443:Tr A
    【学习笔记】〖九度OJ〗题目1104:整除问题
    【学习笔记】〖九度OJ〗题目1138:进制转换
    【学习笔记】〖九度OJ〗题目1326:Waiting in Line
    【学习笔记】〖九度OJ〗题目1437:To Fill or Not to Fill
    【学习笔记】〖九度OJ〗题目1153:括号匹配问题
    【学习笔记】〖九度OJ〗题目1161:Repeater
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/14980457.html
Copyright © 2020-2023  润新知