Codeforces Round 907 (Div. 2) (C 贪心 D套路? F dfs序+差分树状数组)

2023-11-30 05:44

本文主要是介绍Codeforces Round 907 (Div. 2) (C 贪心 D套路? F dfs序+差分树状数组),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

A:

这种操作题,每次先想这个操作有什么性质

对于2^0来说可以操作 第1位

 对于2^1来说可以操作 第1-2位

对于2^2来说可以操作 第1-4位 (第3位无法单独修改)

对于2^3来说可以操作 第1-8位(第5 6 7位无法单独修改)

可以观察到我们要求无法修改的数要按顺序才能满足

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+10,mod= 998244353;
#define int long long
typedef long long LL;
typedef pair<int, int> PII;
const long long inf=1e17;
int n,m,k;
vector<int> g[N];
int a[N];
void solve()
{cin>>n;for(int i=1;i<=n;i++){cin>>a[i];}for(int i=2;i<=5;i++){bool ok=true;// cout<<pow(2,i-1)<<" "<<pow(2,i)<<"\n";for(int j=pow(2,i-1)+1;j<pow(2,i);j++){if(j+1>n||j>n) break;if(a[j]<=a[j+1]) continue;ok=false;}    if(!ok){cout<<"NO\n";return ;}}cout<<"YES\n";
}signed main()
{cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);int t=1;cin>>t;while(t--) solve();
}

B:

操作题,还是想操作当前数x对每个数组a的每个数有啥影响

如果当前数a[i]可以整除2^x,然后加上2^(x-1),那么下次这个数就不能整除2^x

那么他就会变成2^(x-1)的倍数了,他的因子不包含2^x,所以不会再操作

然后x最多30个数,去重后操作即可

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+10,mod=1e9+7;
#define int long long
typedef long long LL;
typedef pair<int, int> PII;
const long long inf=1e17;
int n,m,k;
vector<int> g[N];
int a[N];class BitTree {public:vector<int> tree;int n;BitTree(int _n) : n(_n) {tree.resize(n+1);fill(tree.begin(),tree.end(),0);}inline int lowbit(int x) { return x&-x; }inline void Modify(int x,int v) {for(;x<=n;x+=lowbit(x)) tree[x]+=v;}inline int q(int x) {int ret=0;if(x<=0) return 0;for(;x;x-=lowbit(x)) ret+=tree[x];return ret;}inline int Query(int l,int r) {return q(r)-q(l-1);}
};
int l[N],r[N];
void solve()
{vector<int> b;map<int,int> mp;cin>>n>>m;for(int i=1;i<=n;i++) cin>>a[i];for(int i=1;i<=m;i++){int x;cin>>x;if(mp.count(x)) continue;mp[x]++;b.push_back(x);}for(int i=1;i<=n;i++){int x=a[i];for(auto y:b){if(x%(1<<y)==0){x+=(1<<y-1);}}cout<<x<<" \n"[i==n];}}signed main()
{cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);int t=1;cin>>t;while(t--) solve();
}

C:贪心,肯定是积个大的秒后面数量多的,然后当操作最后一个数的时候,尽量别浪费当前计数器的数,要分奇偶性和1,比如8,前面已经有2了,那么再操作2次,计数器变成4,操作个计数器秒掉,如果当前是8,前面计数器是3,为了不浪费计数器,最后一次肯定是直接消灭而不是使用计数器,所以先-1变成偶数(如果不这样做,最后计数器会多1,次数可能会增加),再换成偶数操作即可,特判1

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+10,mod= 998244353;
#define int long long
typedef long long LL;
typedef pair<int, int> PII;
const long long inf=1e17;
int n,m,k;
vector<int> g[N];
int a[N];
void solve()
{cin>>n;for(int i=1;i<=n;i++) cin>>a[i];sort(a+1,a+1+n);int res=0;int l=1,r=n;int sum=0;while(l<=r){if(a[l]==0){l++;continue;}if(l==r){if(a[l]==1){res++;break;}if((a[l]-sum)%2==1){res+=(a[l]-sum)/2+1;res++;}else{res+=(a[l]-sum)/2+1;}cout<<res<<"\n";return ;}if(a[r]<=sum+a[l]){int x=a[r]-sum;res+=x+1;a[l]-=x;r--;sum=0;}    else{sum+=a[l];res+=a[l];l++;    }}cout<<res<<"\n";
}signed main()
{cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);int t=1;cin>>t;while(t--) solve();
}

D:套路题,求两个区间差即可

然后我画图你应该能看懂

g的函数的值最多有两个不同,因为3 4 5...的增长比2增长快,所以最多两个

可以观察到g的值怎么求

比如8 到 15

用3的倍数求

16到31用 4倍数求他们的g的值,然后乘上求区间个数即可

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+10,mod=1e9+7;
#define int long long
typedef long long LL;
typedef pair<int, int> PII;
const long long inf=1e17;
int n,m,k;
vector<int> g[N];
int a[N];
void solve()
{auto get=[&](int x){int res=0;int c=2;for(int i=4;i<=x;i*=2){int cnt=0;int r=min(x,i*2-1);__int128 now=1;while(now<=i) cnt++,now*=c;c++;if(now>r){res+=(r-i+1)%mod*(cnt-1)%mod;}else{int t=r-now+1;t%=mod;res+=t*cnt%mod+(now-i)%mod*(cnt-1);}}return res%mod;};int l,r;cin>>l>>r;cout<<((get(r)-get(l-1))%mod+mod)%mod<<"\n";
}signed main()
{cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);int t=1;cin>>t;while(t--) solve();
}

F:首先肯定要把数dfs一遍弄出来把,不然鬼知道子树有哪些

然后我们把树画出来

假设 5是新增的节点,我们怎么操作,

直接把前面5节点的数全部减成0即可

然后就是差分咯,因为子树增加是增加整个区间的

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+10,mod=1e9+7;
#define int long long
typedef long long LL;
typedef pair<int, int> PII;
const long long inf=1e17;
int n,m,k;
vector<int> g[N];
int a[N];class BitTree {public:vector<int> tree;int n;BitTree(int _n) : n(_n) {tree.resize(n+1);fill(tree.begin(),tree.end(),0);}inline int lowbit(int x) { return x&-x; }inline void Modify(int x,int v) {for(;x<=n;x+=lowbit(x)) tree[x]+=v;}inline int q(int x) {int ret=0;if(x<=0) return 0;for(;x;x-=lowbit(x)) ret+=tree[x];return ret;}inline int Query(int l,int r) {return q(r)-q(l-1);}
};
int l[N],r[N];
void solve()
{cin>>n;for(int i=1;i<=n*2+10;i++)g[i].clear();vector<array<int,3>>query;int now=1;for(int i=0;i<n;i++){int op;cin>>op;if(op==1){now++;int v;cin>>v;query.push_back({op,v,0});g[v].push_back(now);}else{int v,x;cin>>v>>x;query.push_back({op,v,x});}}int dfn=0;function<void(int)> dfs=[&](int u){l[u]=++dfn;for(auto v:g[u]){dfs(v);}r[u]=++dfn;};dfs(1);BitTree tr(n*2+10);now=1;for(auto [op,v,x]:query){if(op==1){//v增加一个子节点now++;int t=tr.q(l[now]);tr.Modify(l[now],-t);tr.Modify(r[now],t);}else{tr.Modify(l[v],x);tr.Modify(r[v],-x);}}for(int i=1;i<=now;i++){cout<<tr.q(l[i])<<" \n"[i==now];}
}signed main()
{cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);int t=1;cin>>t;while(t--) solve();
}

这篇关于Codeforces Round 907 (Div. 2) (C 贪心 D套路? F dfs序+差分树状数组)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/435845

相关文章

hdu2241(二分+合并数组)

题意:判断是否存在a+b+c = x,a,b,c分别属于集合A,B,C 如果用暴力会超时,所以这里用到了数组合并,将b,c数组合并成d,d数组存的是b,c数组元素的和,然后对d数组进行二分就可以了 代码如下(附注释): #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<que

usaco 1.3 Barn Repair(贪心)

思路:用上M块木板时有 M-1 个间隙。目标是让总间隙最大。将相邻两个有牛的牛棚之间间隔的牛棚数排序,选取最大的M-1个作为间隙,其余地方用木板盖住。 做法: 1.若,板(M) 的数目大于或等于 牛棚中有牛的数目(C),则 目测 给每个牛牛发一个板就为最小的需求~ 2.否则,先对 牛牛们的门牌号排序,然后 用一个数组 blank[ ] 记录两门牌号之间的距离,然后 用数组 an

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while

poj 3159 (spfa差分约束最短路) poj 1201

poj 3159: 题意: 每次给出b比a多不多于c个糖果,求n最多比1多多少个糖果。 解析: 差分约束。 这个博客讲差分约束讲的比较好: http://www.cnblogs.com/void/archive/2011/08/26/2153928.html 套个spfa。 代码: #include <iostream>#include <cstdio>#i

hdu 2489 (dfs枚举 + prim)

题意: 对于一棵顶点和边都有权值的树,使用下面的等式来计算Ratio 给定一个n 个顶点的完全图及它所有顶点和边的权值,找到一个该图含有m 个顶点的子图,并且让这个子图的Ratio 值在所有m 个顶点的树中最小。 解析: 因为数据量不大,先用dfs枚举搭配出m个子节点,算出点和,然后套个prim算出边和,每次比较大小即可。 dfs没有写好,A的老泪纵横。 错在把index在d

poj 3190 优先队列+贪心

题意: 有n头牛,分别给他们挤奶的时间。 然后每头牛挤奶的时候都要在一个stall里面,并且每个stall每次只能占用一头牛。 问最少需要多少个stall,并输出每头牛所在的stall。 e.g 样例: INPUT: 51 102 43 65 84 7 OUTPUT: 412324 HINT: Explanation of the s

poj 3050 dfs + set的妙用

题意: 给一个5x5的矩阵,求由多少个由连续6个元素组成的不一样的字符的个数。 解析: dfs + set去重搞定。 代码: #include <iostream>#include <cstdio>#include <set>#include <cstdlib>#include <algorithm>#include <cstring>#include <cm

poj 3169 spfa 差分约束

题意: 给n只牛,这些牛有些关系。 ml个关系:fr 与 to 牛间的距离要小于等于 cost。 md个关系:fr 与 to 牛间的距离要大于等于 cost。 隐含关系: d[ i ] <= d[ i + 1 ] 解析: 用以上关系建图,求1-n间最短路即可。 新学了一种建图的方法。。。。。。 代码: #include <iostream>#include

poj 2976 分数规划二分贪心(部分对总体的贡献度) poj 3111

poj 2976: 题意: 在n场考试中,每场考试共有b题,答对的题目有a题。 允许去掉k场考试,求能达到的最高正确率是多少。 解析: 假设已知准确率为x,则每场考试对于准确率的贡献值为: a - b * x,将贡献值大的排序排在前面舍弃掉后k个。 然后二分x就行了。 代码: #include <iostream>#include <cstdio>#incl

Codeforces Round #240 (Div. 2) E分治算法探究1

Codeforces Round #240 (Div. 2) E  http://codeforces.com/contest/415/problem/E 2^n个数,每次操作将其分成2^q份,对于每一份内部的数进行翻转(逆序),每次操作完后输出操作后新序列的逆序对数。 图一:  划分子问题。 图二: 分而治之,=>  合并 。 图三: 回溯: