首页 > 其他分享 >题解

题解

时间:2024-07-18 23:07:07浏览次数:12  
标签:std val int 题解 tr long 最小值

A - 地毯

标准的二维差分前缀和,定义 \(s_{i,j}\) 为当前格子的权值,然后根据题目模拟题意进行差分求和即可

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e3 + 10, mod = 1e9 + 7;
int s[N][N];
signed main()
{
    std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int n, m; cin >> n >> m;
    for(int i = 1; i <= m; i++){
        int a, b, c, d; cin >> a >> b >> c >> d;
        s[a][b] ++, s[a][d + 1] --, s[c + 1][b] --, s[c + 1][d + 1] ++;
    }
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            s[i][j] = s[i][j] + s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1];
            cout << s[i][j] << ' ';
        }
        cout << '\n';
    }
    return 0;
}

B - FBI树

根据题意模拟,首先把节点数变成应该的长度即 \(2^n\),进行两边 \(dfs\),第一遍类似于线段树保存节点以及区间信息,这里注意如果两个儿子相同也有可能是 F,因为有一个是F那么就是F。接下来进行第二遍 \(dfs\),首先判断叶子节点,然后判断左右儿子,最后判断根节点。

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6 + 10, mod = 1e9 + 7;
struct node{
    int l, r;
    char val;
};
signed main()
{
    std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int n; cin >> n;
    n = 1 << n;
    string s; cin >> s;
    s = " " + s;
    vector<node> tr(n * 4 + 1);
    function<void(int, int, int)> dfs1;
    dfs1 = [&](int u, int l, int r) -> void{
        if(l == r){
            if(s[l] == '1') tr[u] = {l, r, 'I'};
            else if(s[l] == '0') tr[u] = {l, r, 'B'};
            else tr[u] = {l, r, 'F'};
            return;
        }
        tr[u] = {l, r};
        int mid = l + r >> 1;
        dfs1(u << 1, l, mid), dfs1(u << 1 | 1, mid + 1, r);
        if(tr[u << 1].val == tr[u << 1 | 1].val){
            if(tr[u << 1].val == 'I') tr[u].val = 'I';
            else if(tr[u << 1].val == 'B') tr[u].val = 'B';
            else tr[u].val = 'F';
        }
        else tr[u].val = 'F';
    };
    function<void(int)> dfs2;
    dfs2 = [&](int u) -> void{
        if(tr[u].l == tr[u].r){
            cout << tr[u].val;
            return;
        }
        dfs2(u << 1), dfs2(u << 1 | 1);
        cout << tr[u].val; 
    };
    dfs1(1, 1, n);
    dfs2(1);
    return 0;
}

H - 良好的感觉

本题稍微有点怪,本来以为是 \(dp\),虽然列出方程之后发现 \(1~i\) 之间的最小值与区间和乘积较难维护,于是考虑贪心是否可行,我们可以直接考虑枚举最小值,这样的枚举次数为 \(O(n)\),定义一个结构体维护信息: 权值 \(val\) 和位置 \(id\),接下来考虑如何去贪心。

考虑由一个最小值组成的答案是一定的,也就是从最小值这个位置向左右扩展,左边和右边直到遇到一个比它小的位置停止,那么明显的,这个区间即是我们钦定这个最小值能做到的最大贡献,统计即可,这样做一定是对的,因为不存在另一个以这个数为最小值的更大区间。

那么我们从小到大排序,每枚举一个数就打上标记,那么我们在左右扩展中遇到标记过的就停止即可,那么一共打上了 \(n\) 个标记,时间复杂度为 \(O(nlogn + n)\),但是由于题目中的数值均不大于 \(10^6\),故我们可以使用桶排序优化到 \(O(n + n)\)

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6 + 10, mod = 1e9 + 7;
struct node{
    int val, id;
    bool operator<(const node &w) const{
        return val < w.val;
    }
}a[N];
int s[N];
bool vis[N];
signed main()
{
    std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int n; cin >> n;
    for(int i = 1; i <= n; i++){
        int x; cin >> x; 
        a[i] = {x, i};
        s[i] = s[i - 1] + a[i].val;
    }
    sort(a + 1, a + 1 + n);
    int res = a[1].val * s[n];
    vis[0] = true, vis[a[1].id] = true;
    for(int i = 2; i <= n; i++){
        int l = a[i].id, r = a[i].id;
        while(l && !vis[l - 1]) l --;
        while(r < n && !vis[r + 1]) r ++;
        res = max(res, a[i].val * (s[r] - s[l - 1]));
        vis[a[i].id] = true;
    }
    cout << res << '\n';
    return 0;
}

标签:std,val,int,题解,tr,long,最小值
From: https://www.cnblogs.com/o-Sakurajimamai-o/p/18310576

相关文章

  • 题解:2024牛客多校赛第二场 A Floor Tiles(思维)
    2024NowcoderMulti-UniversityTrainingContest2ProblemA.FloorTiles题目大意给你两种正方形图案,分别为以下两种:再给你三个整数\(N,M,K\),表示你需要用这两种图案,拼成一个\(N\)列\(M\)行的矩形。由于这两种图案十分特殊,他们能无缝衔接在一起。因此你需要让这个矩......
  • GESP编程能力等级认证C++编程真题解析 | 2024年3月五级
    学习C++从娃娃抓起!记录下CCF-GESP备考学习过程中的题目,记录每一个瞬间。附上汇总贴:GESP编程能力等级认证C++编程真题解析|汇总单选题第1题唯一分解定理描述的内容是()?A.任意整数都可以分解为素数的乘积B.每个合数都可以唯一分解为一系列素数的乘积C.两个不同的......
  • 题解:CF1912D Divisibility Test
    又是一道水绿。刚刚小学毕业的数学idiot——我释怀地笑了。第一种很好判断,当$b^k$为$n$的倍数时,取基数为$b$的能被$n$整除的整数$c$的最后$k$位数显然能被$n$整除。第二种也不难,当$b^k\equiv1\pmodn$时,取以$b$为底数的能被$n$整除的整数$c$的$k$......
  • Load balancer does not contain an instance for the service service-B [503] duri
    场景:service-A服务通过openFeign远程调用service-B服务的test()方法,结果报错Loadbalancerdoesnotcontainaninstancefortheserviceservice-Bfeign.FeignException$ServiceUnavailable:[503]during[POST]to[http://service-B/test]原因:报错信息的意思......
  • [题解]P1896互不侵犯
    数位DP模板题link题面[SCOI2005]互不侵犯题目描述在\(N\timesN\)的棋盘里面放\(K\)个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共\(8\)个格子。输入格式只有一行,包含两个数\(N,K\)。输出格......
  • T3 飞刀传承 题解
    题目描述李家自古以来就是飞刀名门,每一任家主都唤作小李。这一代的小李更是青出于蓝,将祖传的飞刀绝技使得出神入化,年纪轻轻便继承了李家祖传的招式,担下了家主之位。不料有日凶兽来袭,李家满门几尽被灭,只剩少数流落在外的弟子得以幸存。他一度想要自尽,却因李家飞刀绝技不能在他手上......
  • T2 替换字母2 题解
    题目描述:有长度为\(n\)的字符串,仅包含小写字母。小信想把字符串变成只包含一种字母。他每次可以选择一种字符\(c\),然后把长度最多为\(m\)的子串中的字符都替换成\(c\)。小信想知道最少需要操作几次能让字符串只包含一种字母。题意简述给定一个长度为\(n\)的小写字母串,每次可以......
  • T1 此方的身高排序 题解
    题目描述:体育馆里有\(n\)个人正在排队等待着上体育课,他们每个人都不一样高。此方想要把队伍从小个子到高个子进行排序,即让队伍身高为升序。此方每次调出一人,让此人和在他后面的人比身高,如果比对方高,则两人交换位置并和下一个人继续比较,直到比对方矮或者已经在队尾。现在给出......
  • CF208E 题解
    BloodCousins前置知识:线段树合并。我们先把题目转化一下。这里先设\(v\)的\(p\)级祖先为\(u\),事实上要求的东西就是\(u\)的\(p\)级后代的个数减\(1\),减\(1\)是因为要把自己减去。显然这个目标点\(t\)要满足两个要求:\(t\)在\(u\)子树内。设\(dep_u\)表......
  • P3242 接水果 题解
    Statement树,给\(m\)条带权路径\((a,b,v)\),\(q\)次询问包含\((u,v)\)的路径中的第\(k\)小权值.Solution好题!这篇题解延伸出了很多东西。首先路径的包含关系转为矩形(二维限制关系)是比较显然的.具体地,\((u,v)\)包含\((a,b)\)有两种情况:\(u,v\)无祖先关系:\(a\)在......