首页 > 其他分享 >1.11-1.15做题笔记

1.11-1.15做题笔记

时间:2025-01-15 17:12:30浏览次数:1  
标签:rt 1.15 1.11 int sum 节点 做题 ls 线段

说句闲话

主要记录了一模考完之后做的一些题,有难的也有比较简单的,都是一些不属于任何比赛的题,所以放在这里统一记录了。

P3551 [POI2013] USU-Take-out

题目大意

有 \(n\) 块砖,其中白色是黑色的 \(k\) 倍,求一个消除序列,满足以下条件:

每次消除 \(k+1\) 个砖,其中 \(k\) 块白色,\(1\) 块黑色,并且这 \(k+1\) 块砖从开始到结束,中间不能路过已经消除过的砖。

解题思路

这个问题看似很棘手:怎样保证中间不能路过已经消除过的砖块?

可以手模一下样例,就会发现,一个比较优的策略是先将取两边的砖块,最后取中间的砖块,但是这样很难实现。

这时候可以考虑反向思考,如果是按照这样的策略,那么最后一组序列就会是在中间的一段连续区间,根据这个突破口,我们不难得到以下做法:

维护一个栈,当栈顶有连续的一段区间中恰好满足白色 \(1\) 个,黑色 \(k\) 个的条件,就将这 \(k+1\) 个元素弹出,依此类推,只要栈顶有连续 \(k+1\) 个元素满足要求就弹出,最终将弹出的元素倒序输出就是正确方案。

判断满足要求可以将白色砖块赋值为 \(1\),黑色砖块赋值为 \(0\),再用前缀和维护。

for(int i=1;i<=n;i++){
    stk.push(i);

    int top=stk.size();
    sum[top]=sum[top-1]+(s[i-1]=='c'); 

    if(stk.size()<k+1)continue;
    if(sum[top]-sum[top-k-1]==1){
        int j=0;
        while(j<=k){
            output.push_back(stk.top());
            j++,stk.pop();
        }
        //stk.pop_k(k+1);
    }
}

for(int i=output.size()-1;i>=0;i--){
    cout<<output[i]<<" ";
    if(i%(k+1)==0)cout<<"\n";
}

P11148 [THUWC 2018] 零食

题目大意

有两种物品价值为 \(a_i\) 与 \(b_i\) 分别 \(n\) 个和 \(m\) 个,现在将两种物品放到同一个序列中,如果当前物品类型与上一个物品相同,则总价值会加上当前物品价值 \(a_i\) 或 \(b_i\),若类型不同,则总价值不变。

求解最大的总价值。

\(a_i\) 和 \(b_i\) 都有可能是负数

题目思路

贪心地思考问题,最优的情况肯定是正的价值全部算入总价值,负的价值全部不算。

考虑如何尽量让负的价值全都不算呢?将负的物品 \(a\) 与物品 \(b\) 交替放置是显然的。

那么就可以直接确定策略:

先将 \(a\) 与 \(b\) 分别由小到大排序,计算前缀和 \(suma\) 以及 \(sumb\),然后就可以线性枚举求出最大值。

注意开 long long。

sort(a+1,a+1+n);
sort(b+1,b+1+m);

ll ans=-1ll<<62;
for(int i=n;i>=1;i--){
    sum_a[i-1]=sum_a[i]+a[i];
}
for(int i=m;i>=1;i--){
    sum_b[i-1]=sum_b[i]+b[i];
}
for(int i=1;i<=min(n,m);i++){
    ans=max(ans,sum_a[i]+sum_b[i]);
    if(i<n)ans=max(ans,sum_a[i+1]+sum_b[i]);
    if(i<m)ans=max(ans,sum_a[i]+sum_b[i+1]);
}

P4556 [Vani有约会] 雨天的尾巴 /【模板】线段树合并

线段树合并的模板题。

首先学习了动态开点线段树,在线段树的 build 函数中维护两个数组 lsrs

线段树合并的主要过程:

假设两颗线段树为 A 和 B,从 \(1\) 号节点开始递归合并。

递归到某个节点时,如果 A 树或者 B 树上的对应节点为空,直接返回另一个树上对应节点,运用了动态开点线段树的特性

如果递归到叶子节点,我们合并两棵树上的对应节点。

最后,根据子节点更新当前节点并且返回。

对于本题,用差分把树上修改转化为单点修改,然后向上 dfs 线段树合并统计答案即可。

这里是线段树合并的模板。

struct Seg_Tree{
    int cnt=0;
    int sum[N*50],res[N*50];
    int ls[N*50],rs[N*50];
    
    void push_up(int rt) {
        if(sum[ls[rt]]<sum[rs[rt]]){
            res[rt]=res[rs[rt]],sum[rt]=sum[rs[rt]];
        } 
        else{
            res[rt]=res[ls[rt]],sum[rt]=sum[ls[rt]];
        }
    }

    void merge(int &a,int b,int l,int r){
        if(!a){
            a=b;
            return;
        }
        if(!b){
            return;
        }

        if(l==r){
            sum[a]+=sum[b];
            return;
        }

        int md=(l+r)>>1;
        merge(ls[a],ls[b],l,md);
        merge(rs[a],rs[b],md+1,r);
        push_up(a);

        return;
    }

    void add(int &rt,int l,int r,int p,int x){
        if(!rt){
            rt=++cnt;
        }
        if(l==r){
            sum[rt]+=x,res[rt]=p;
            return;
        }
        int md=(l+r)>>1;
        if(p<=md){
            add(ls[rt],l,md,p,x);
        }
        else{
            add(rs[rt],md+1,r,p,x);
        }
        push_up(rt);
        
        return;
    }
}Tr;

P10242 [THUSC 2021] Emiya 家明天的饭

首先可以钦定每个菜满足哪些人的需求,问题就被转化为了求解:

$\sum S \sum {i \in S} \sum f \(,\)f$ 表示每一行的超集和。

求解超集和可以使用状压dp,时间复杂度 \(O(n^2\times 2^n)\)。

for(int j=1;j<=m;j++){
    int tmp=0;
    for(int i=1;i<=n;i++)
        if(a[i][j]!=-1){
            tmp|=1<<i-1;
        }
    for(int i=1;i<=n;i++)
        if(a[i][j]!=-1){
            f[i][tmp]+=a[i][j];
        }
}

for(int i=1;i<=n;i++)
    for(int j=0;j<n;j++)
        for(int k=0;k<(1<<n);k++){
            if(!(k&(1<<j))){
                f[i][k]+=f[i][k|(1<<j)];
            }
        }

ll maxn=0;
for(int i=0;i<(1<<n);i++){
    ll sum=0;
    for(int j=1;j<=n;j++){
        if(i&(1<<j-1)){
            sum+=f[j][i];
        }
    }
    maxn=max(maxn,sum);
}

cout<<maxn<<"\n";

标签:rt,1.15,1.11,int,sum,节点,做题,ls,线段
From: https://www.cnblogs.com/Sunbutstfan1106/p/18673166

相关文章

  • ABC243做题笔记
    AtcoderBeginnerContest243D-MovesonBinaryTree题目大意有一棵极大的二叉树,有\(2^{10^{100}}-1\)个节点,给定一些操作,输出在线段树上遍历后的最后的节点的编号。解题思路如果直接模拟,显然数据太大,会远超出longlong的范围。有一个条件非常重要:最终的答案在long......
  • 2025.1.15日志
    2025.1.141.实现了人物的待机,走路,跑步的动画以及其代码逻辑实现。其中,(待机/走路),(跑步)在动画机BlendTree中的参数用yVelocity,xVelocity表示,  privatevoidAnimatorController()  {    floatyVelocity=Vector3.Dot(moveDir.normalized,transform.f......
  • ABC224做题笔记
    AtcoderBegineerContest224D-8PuzzleonGraph题目大意给定一个\(9\)个顶点,\(m\)条边的图,共有八个棋子分别在\(p_1,p_2,p_3...p_8\),问最终能否让第\(i\)个棋子放在\(i\)号节点上。解题思路考虑与八数码相同的做法。将九个顶点对应的状态压缩成一个九位数,即每......
  • 做题随笔:P10465
    Solution这里是博客:Tenil,刚刚用上了JS,不妨看看?题意原题链接给定数列\(a_N\),按以下要求分为\(n\)组:每组中的数单调不降。每组中的数在原数列中的下标单调递减/单调递增/先递减再递增。(思考一下双向队列插入值的过程显然有:越往两端的越后入队)存在一种方法,使所有分组拼接......
  • 【cs.CV】25.1.11 arxiv更新速递
    25.1.1012:00-25.1.1112:00共更新99篇—第1篇----=====DecentralizedDiffusionModels......
  • 1.11鲜花
    感觉这两天停课有点不太对劲……本身因为csp-s打烂了赛季报销之后就没有什么事了的,车人却还要以T/P营赛前要拉进度的理由把我们喊过来停课。说实话本身还是想停课的,但停了了一天就发现T和P都去不了,最后车人拉进度又拉的奇快无比(例如放一个一上午的题单有一堆多项式与生......
  • 2024.11.15(maven javascript)
    编写pom.xml文件在项目根目录下的pom.xml文件中,添加JUnit依赖和配置:4.0.0<groupId>com.example</groupId><artifactId>my-maven-project</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>1.8&l......
  • 2024.11.11(spring boot创建数据库)
    完整代码UserControllerpackagecom.example.springboot.controller;importcom.example.springboot.pojo.User;importcom.example.springboot.service.UserService;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.bind.a......
  • 泛做题记录
    伊基的故事I-道路重建网络流题,在跑完dinic后,在残量网络上找\(f(u,v)=0\),满足存在\(s\rightarrowu,v\rightarrowt\)的边。代码。[USACO05FEB]SecretMilkingMachineG网络流题,明显二分答案。网络可以直接建反向边,因为流两次相当于没流。codeconstintN=......
  • [CF1019C] Sergey's problem 做题记录
    小清新构造题,会就会,不会就不会。link注意到走两步很特殊,尝试从走一步拼出来,考虑归纳法:随便选择一个点\(x\),然后删掉\(x\)和所有\(y\)满足存在边\((x,y)\)。设剩下的图的答案集合为\(S\),若不存在\(z\inS\)满足存在边\((z,x)\),则将\(x\)加入\(S\)。否则......