首页 > 其他分享 >CSP模拟25

CSP模拟25

时间:2023-08-19 20:35:27浏览次数:56  
标签:25 结点 int long flag que sqrt CSP 模拟

炒币、凑数、同构、最近公共祖先

A. 炒币

举个栗子,对于序列

\[1,4,5 \]

在 \(1\) 处买进,在 \(5\) 处卖出是最优的选择。

为什么不选择在 \(4\) 处买,因为 \(4\) 处成本更高,所以我们可以把一段递增或递减的序列缩成几个互不相同的点。

例如

\[1,3,5,3,2,7 \]

变成

\[5,2,7 \]

只有这几个点是需要操作的。

若操作后的序列长度为偶数,直接输出;如果长度为奇数,不在第最后一个点把钱换成比特币。

#include <bits/stdc++.h>

using namespace std;

const int N = 500500;

int n;
long long a[N];

vector< pair<long long,int> > que;

bool vis[N];

int main() {
    scanf("%d",&n);

    for(int i = 1;i <= n; i++) {
        cin >> a[i];
    }

    bool flag = 0;

    if(a[1] > a[2]) {
        que.emplace_back(a[1],1);
        flag = 1;
    }

    for(int i = 2;i <= n; i++) {
        if((flag == 0 && a[i] >= a[i - 1]) && (a[i + 1] < a[i] || i == n)) {
            flag = 1;
            que.emplace_back(a[i],i);
        }
        else if((flag == 1 && a[i] <= a[i - 1]) && (a[i + 1] > a[i] || i == n)) {
            flag = 0;
            que.emplace_back(a[i],i);
        }
    }

    if(que.empty()) {
        for(int i = 1;i <= n; i++)
            cout << "0 ";
        return 0;
    }

    if(que.size() % 2 == 0) {
        for(auto const &it : que) {
            vis[it.second] = 1;
        }
        
        for(int i = 1;i <= n; i++)
            cout << vis[i] << " ";
        return 0;
    }
    else {
        if(que.size() == 1) {
            for(int i = 1;i <= n; i++) 
                cout << "0 ";
            
            return 0;
        }

        for(auto const &it : que) 
            vis[it.second] = 1;
        
        vis[que.back().second] = 0;

        for(int i = 1;i <= n; i++)
            cout << vis[i] << " ";

        return 0;
    }
    return 0;
}

B. 凑数

我们钦定 \(a\) 的性价比不低于 \(b\),如果不满足就交换。

最多只能取 \(\left\lfloor \dfrac{n}{a} \right\rfloor\) 个 \(a\),最多只能取 \(a-1\) 个 \(b\)。如果选 \(a\) 个 \(b\) 的话,我们完全可以用 \(b\) 个 \(a\) 来代替它,这样不是更优的,所以 \(b\) 最多取 \(a-1\) 个。

于是有策略:

  1. 如果 \(a \leq \sqrt{n}\),那么我们枚举 \(b\) 的数量;
  2. 如果 \(a \geq \sqrt{n}\),那么就有 \(\left\lfloor \frac{n}{a} \right\rfloor \leq \sqrt{n}\),就枚举 \(a\) 的数量。

这两种方法枚举次数都不超过 \(\sqrt{n}\),所以时间复杂度约为 \(\operatorname{O}(\sqrt{n})\)。

#include <bits/stdc++.h>

using namespace std;

int T;

long long n,a,b,x,y,z;

long long ans,tmp;

double val1,val2,val3;

void Work() {
    ans = LLONG_MAX;

    if(a * z < y * b) {
        swap(a,b);
        swap(y,z);
    }

    if(a * x <= y) {
        ans = n * x;
        return ;
    }

    if(b * x <= z) {
        ans = n / a * y + n % a * x;
        return ;
    }

    if(n / a < a - 1) {
        for(int i = 0;i <= (n / a); i++) {
            tmp = n - i * a;
            ans = min(ans,i * y + tmp / b * z + tmp % b * x);
        }
    }
    else {
        for(int i = 0;i <= a - 1; i++) {
            tmp = n - i * b;
            if(tmp >= 0)
                ans = min(ans,i * z + tmp / a * y + tmp % a * x);
        }
    }
    return ;
}

int main() {
#ifdef ONLINE_JUDGE == 1
    freopen("cs.in","r",stdin);
    freopen("cs.out","w",stdout);
#endif
    scanf("%d",&T);

    while(T--) {
        cin >> n >> a >> b >> x >> y >> z;
        
        Work();

        cout << ans << "\n";
    }

    fclose(stdin);
    fclose(stdout);
    return 0;
}

C. 同构

D. 最近公共祖先

考虑维护一个结点与其他所有被染色结点的权值最大的最近公共祖先权值,考虑线段树维护。

每次如何维护?

对于这棵树,我们要染色 \(3\) 号结点,我们需要维护的是它父亲结点的子树除了它之外的子树,而不去维护它自己的子树。

因为它自己子树中的点与染色的点的会被更外面的点维护,例如 \(10\) 号结点被染色的时候 \(4\) 号结点会被维护。

#include <bits/stdc++.h>

using namespace std;

const int N = 100500;

int n,m;

int val[N];

struct Edge{
    int next,to;
}e[N << 1];

int cnt,h[N];

void Add(int u,int v) {
    cnt ++;
    e[cnt].next = h[u];
    h[u] = cnt;
    e[cnt].to = v;

    return ;
}

int dfn[N],tot,fa[N];

int lim[N];
// 子树最大 dfn 

// Ready For Dfn
void dfs1(int x,int from) {
    fa[x] = from;
    tot ++;
    dfn[x] = tot;
    lim[x] = tot;

    for(int i = h[x];i; i = e[i].next) {
        int to = e[i].to;
        if(to == from)
            continue;
        
        dfs1(to,x);

        lim[x] = max(lim[x],lim[to]);
    }
}

// Segment Tree
int data[N];

#define lid id << 1
#define rid id << 1 | 1

class SegmentTree{
private:
    void Pushdown(int id) {
        data[lid] = max(data[lid],data[id]);
        data[rid] = max(data[rid],data[id]);
    }
public:
    void Update(int id,int l,int r,int L,int R,int k) {
        if(L <= l && r <= R) {
            data[id] = max(data[id],k);
            return ;
        }

        Pushdown(id);

        int mid = (l + r) >> 1;

        if(L <= mid) 
            Update(lid,l,mid,L,R,k);
        if(mid + 1 <= R)
            Update(rid,mid + 1,r,L,R,k);
    }

    int Query(int id,int l,int r,int pos) {
        if(l == r)
            return data[id];
        
        Pushdown(id);

        int mid = (l + r) >> 1;

        if(pos <= mid)
            return Query(lid,l,mid,pos);
        else
            return Query(rid,mid + 1,r,pos);
    }
}tree;

#undef lid
#undef rid

// Main
bool vis[N];

void Revise(int x,int from) {
    if(x == from)
        tree.Update(1,1,n,dfn[x],lim[x],val[x]);
    else {
        tree.Update(1,1,n,dfn[x],dfn[from] - 1,val[x]);

        if(lim[from] < lim[x])
            tree.Update(1,1,n,lim[from] + 1,lim[x],val[x]);
    }
}

void Modify(int x,int from) {
    Revise(x,from);

    if(vis[x])
        return ;
    vis[x] = 1;

    if(x == 1)
        return ;

    Modify(fa[x],x);
}

int main() {
    ios::sync_with_stdio(false);
    
    cin >> n >> m;
    for(int i = 1;i <= n; i++)
        cin >> val[i];
    
    for(int i = 1,u,v;i < n; i++) {
        cin >> u >> v;
        Add(u,v);
        Add(v,u);
    }

    dfs1(1,0);

    string str;
    int x;
    bool flag = 0;

    for(int i = 1;i <= m; i++) {
        cin >> str >> x;
        if(str == "Modify") {
            flag = 1;
            Modify(x,x);
        }
        else {
            if(!flag) {
                cout << "-1\n";
                continue;
            }

            cout << tree.Query(1,1,n,dfn[x]) << "\n";
        }
    }
    return 0;
}

标签:25,结点,int,long,flag,que,sqrt,CSP,模拟
From: https://www.cnblogs.com/baijian0212/p/csp-25.html

相关文章

  • 普及模拟2 +【LGR-155-Div.3】洛谷基础赛 #3 &「NnOI」Round 2
    普及模拟2\(T1\)地址\(0pts\)简化题意:判断一个\(IP\)地址是否合法(数据保证字符串中存在且仅存在4个被字符分开的整数)#include<bits/stdc++.h>usingnamespacestd;#definelllonglong#definesortstable_sort#defineendl'\n'chars[100];intmain(){ freope......
  • 【25.0】路飞支付相关
    【一】订单相关表设计Order订单表OrderDetail订单详情表fromdjango.dbimportmodelsfromluffyCity.apps.course.modelsimportCoursefromluffyCity.apps.user.modelsimportUser#Order订单表classOrder(models.Model):"""订单模型"""......
  • python模拟用户pa取
    使用Selenium模拟用户爬取页面内容,并输出成文件。关于Selenium是什么,欢迎看这篇文章:seleniumPython教程。在这里,我只讲我主要的实现。首先作为一款工具脚本,我们应该不喜欢窗口界面吧,除非你需要动态的观察程序的操作。所以,我开启了无头浏览器模式#无头浏览器chrome_options=webd......
  • python生成模拟数据
    python faker的使用Faker是一个Python包,开源的GITHUB项目,主要用来创建伪数据,使用Faker包,无需再手动生成或者手写随机数来生成数据,只需要调用Faker提供的方法,即可完成数据的生成安装pipinstallFaker使用fromfakerimportFakerfaker=Faker(locale='zh_CN')fromfakerimportF......
  • Virtualbox安装Linux使用2560以上高分辨率黑屏
    Virtualbox安装Linux后,通过VirtualBox的视图菜单默认只有1920的分辨率可供选择,想要使用更高分辨率(比如4K)需要在Linux系统的设置里选择。但是,通过Linux系统菜单设置分辨率达到2560时,虚拟机就会黑屏,只有鼠标。此时系统仍然正常运行,按esc可取消当前设置,按回车会确认当前设置,然后就黑......
  • P9425 [蓝桥杯 2023 国 B] AB 路线 题解
    ~~应该能过官方数据吧~~---回归正题。我开始想过更简单的深搜,但是我怕无法记忆化,所以选择了广搜。和普通的广搜不同,此题的队列要存$3$个维度,分别是$x$,$y$,$z$,分别表示横坐标、纵坐标、目前的步数模$2k$的值。此时我们可以把每$2k$步进行分组,前$k$步走在```A```的格子......
  • 8.19 模拟赛小结
    前言结束了也许这几天很苦但也是最有意义的几天这篇写简单一点吧T1颠倒黑白很强的构造题根据打表找出思路因为最左下角的是一定要点的就考虑它如果是先手左下角有黑色就把它点了后手只能帮我们把其它黑色点了最后还是我们先点完若是后手左下角是白色与先手同......
  • 【csp-3】排列与组合
    组合:n个数选m个数,从小到大第k个选择是什么#include<cstdio>#include<iostream>#include<algorithm>#include<cstring>#include<bits/stdc++.h>usingnamespacestd;intflag,n,m,a[21],vis[21],k,sum;voiddfs(intnow,intlast){if(flag==1)re......
  • 【考后总结】8 月 CSP-S 模拟赛 7
    8.19CSP模拟25给我一首歌的时间-周杰伦雨淋湿了天空毁得很讲究你说你不懂为何在这时牵手我晒干了沉默悔得很冲动就算这是做错也只是怕错过在一起叫梦分开了叫痛是不是说没有做完的梦最痛迷路的后果我能承受这最后的出口在爱过了才有能不能给我一首歌的时......
  • 【刷题笔记】25. Reverse Nodes in k-Group
    题目Givenalinkedlist,reversethenodesofalinkedlistkatatimeandreturnitsmodifiedlist.kisapositiveintegerandislessthanorequaltothelengthofthelinkedlist.Ifthenumberofnodesisnotamultipleofkthenleft-outnodesint......