A - Cubes Sorting

冒泡排序交换次数等于逆序对数,严格降序需要交换n(n−1)2\frac{n(n-1)}{2}2n(n−1)​次才能升序排列,由此只需要判断原数组是否严格降序即可。

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<iostream>
#include<algorithm>
using namespace std;
const int N=500010;
int a[N];
int n;
int main()
{IO;int T=1;cin>>T;while(T--){bool ok=1;cin>>n;for(int i=1;i<=n;i++){cin>>a[i];if(i>1&&a[i]>=a[i-1]) ok=0;}if(ok) cout<<"NO\n";else cout<<"YES\n";}return 0;
}

B - Rock and Lever

按位考虑,随便搞搞

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<iostream>
#include<algorithm>
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int N=500010;
int a[N];
int cnt[40];
int n;
int main()
{IO;int T=1;cin>>T;while(T--){bool ok=1;cin>>n;memset(cnt,0,sizeof cnt);for(int i=1;i<=n;i++){cin>>a[i];bool ok=1;for(int j=31;j>=0;j--)if(ok&&(a[i]>>j&1)){cnt[j]++;ok=0;break;}}ll res=0;for(int i=31;i>=0;i--)if(cnt[i])res+=1ll*cnt[i]*(cnt[i]-1)/2;cout<<res<<'\n';}return 0;
}

C1 - Pokémon Army (easy version)

不带修改,直接dp扫一遍。

状态表示:f(i,0)f_{(i,0)}f(i,0)​考虑前iii个数,并且选择第iii个数状态是+,f(i,1)f_{(i,1)}f(i,1)​考虑前iii个数,并且选择第iii个数状态是-
状态转移:f(i,0)=max(f(i,0),f(k,1)+ai)f_{(i,0)}=max(f_{(i,0)},f_{(k,1)}+a_i)f(i,0)​=max(f(i,0)​,f(k,1)​+ai​),f(i,1)=max(f(i,1),f(k,0)−ai)f_{(i,1)}=max(f_{(i,1)},f_{(k,0)}-a_i)f(i,1)​=max(f(i,1)​,f(k,0)​−ai​),(1<k<i1<k<i1<k<i)只需要在维护2个前缀最大值即可O(n)O(n)O(n)得到答案。

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<iostream>
#include<algorithm>
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int N=300010;
const int INF=1e17;
ll a[N],f[N][2];
int n,q;
int main()
{IO;int T=1;cin>>T;while(T--){cin>>n>>q;for(int i=1;i<=n;i++) cin>>a[i];for(int i=1;i<=n;i++) f[i][0]=f[i][1]=-INF;f[0][0]=-INF;ll mmax0=-INF,mmax1=0;ll res=-INF;for(int i=1;i<=n;i++){f[i][0]=mmax1+a[i];f[i][1]=mmax0-a[i];mmax0=max(mmax0,f[i][0]);mmax1=max(mmax1,f[i][1]);res=max(res,max(f[i][0],f[i][1]));}cout<<res<<'\n';}return 0;
}

Pokémon Army (hard version)

用线段树维护fff数组即可,对于线段树每一个区间维护数组f[2][2]f[2][2]f[2][2]。
f[0][0]f[0][0]f[0][0]表示序列开头+,结尾+
f[0][1]f[0][1]f[0][1]表示序列开头+,结尾-
f[1][0]f[1][0]f[1][0]表示序列开头-,结尾+
f[1][1]f[1][1]f[1][1]表示序列开头-,结尾-

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int N=300010;
const ll INF=1e17;
ll a[N];
int n,q;
// f[0][0] ++
// f[0][1] +-
// f[1][0] -+
// f[1][1] --
struct node
{int l,r;ll val;ll f[2][2];
}tree[N*4];
void pushup(int u)
{tree[u].val=-INF;for(int i=0;i<2;i++)for(int j=0;j<2;j++){tree[u].f[i][j]=max(tree[u<<1].f[i][j],tree[u<<1|1].f[i][j]);tree[u].f[i][j]=max(tree[u].f[i][j],max(tree[u<<1].f[i][0]+tree[u<<1|1].f[1][j],tree[u<<1].f[i][1]+tree[u<<1|1].f[0][j]));tree[u].val=max(tree[u].val,tree[u].f[i][j]);}
}
void build(int u,int l,int r)
{tree[u]={l,r};if(l==r){tree[u].val=a[l];tree[u].f[0][0]=a[l];tree[u].f[1][1]=-a[l];tree[u].f[0][1]=tree[u].f[1][0]=-INF;return;}int mid=l+r>>1;build(u<<1,l,mid);build(u<<1|1,mid+1,r);pushup(u);
}
void modify(int u,int p,int x)
{if(tree[u].l==tree[u].r){tree[u].val=x;tree[u].f[0][0]=x;tree[u].f[1][1]=-x;tree[u].f[0][1]=tree[u].f[1][0]=-INF;return;}int mid=tree[u].l+tree[u].r>>1;if(p<=mid) modify(u<<1,p,x);else modify(u<<1|1,p,x);pushup(u);
}
int main()
{IO;int T=1;cin>>T;while(T--){cin>>n>>q;for(int i=1;i<=n;i++) cin>>a[i];build(1,1,n);cout<<tree[1].val<<'\n';while(q--){int l,r;cin>>l>>r;modify(1,l,a[r]);modify(1,r,a[l]);cout<<tree[1].val<<'\n';swap(a[l],a[r]);}}return 0;
}

D - Rescue Nibel!

先上课去了,晚上回来写。第一次数组开小了还re了

先把每个区间的左端点和右端点拆开记录下来,然后排个序(注意:先按照位置排序,按照左端点优先原则排序)借用扫描线的思想扫描整个序列。
扫描的过程中,如果到一个左端点说明目前有一盏灯在此时刻点亮那么对答案的贡献就是在需要从前面点亮的灯中选择k−1k-1k−1盏灯,维护前面点亮灯的数量只需要维护一个cnt即可,那么对答案的贡献即Ccntk−1C_{cnt}^{k-1}Ccntk−1​,然后更新cnt即可,如果扫描到一个右端点不难发现对答案没有贡献,只需要维护cnt即可。
计算Ccntk−1C_{cnt}^{k-1}Ccntk−1​的过程中由于既要取模又有除法需要提前预处理阶乘和逆元。

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int N=300010;
const ll mod=998244353;
pii a[2*N];
int n,k;
ll qmi(ll a,ll b,ll p)
{ll res=1;while(b){if(b&1) res=res*a%p;b>>=1;a=a*a%p;}return res;
}ll fact[N],infact[N];
void init(int n)
{fact[0]=infact[0]=1;for(int i=1;i<=n;i++){fact[i]=fact[i-1]*i%mod;infact[i]=qmi(fact[i],mod-2,mod);}
}
int main()
{IO;int T=1;//cin>>T;while(T--){cin>>n>>k;init(n);for(int i=1;i<=n;i++){int l,r;cin>>l>>r;a[i].first=l,a[i].second=-1;//左端点a[i+n].first=r,a[i+n].second=1;//右端点}sort(a+1,a+1+2*n);ll res=0;ll cnt=0;for(int i=1;i<=2*n;i++){int p=a[i].first,id=a[i].second;if(id==-1){if(cnt>=k-1)res=(res+fact[cnt]*infact[k-1]%mod*infact[cnt-k+1]%mod)%mod;cnt++;}else cnt--;}cout<<res<<'\n';}return 0;
}

E - Battle Lemmings

我还是不会难的dp
whd大佬视频题解

为什么能用dp?
首先有一点非常重要:无论如何移动1,所有1的相对位置并不会改变。因此考虑答案的集合肯定是将这些1不改变相对位置的情况下排到某些位置,而代价即移动的步数可以通过原先位置和当前位置算出来,那么如果我们逐一考虑每一个1最终的位置不难发现这个问题是无后效性的。

如何算出答案?
最终要求算一个很奇怪的东西,就是两个0之间只要存在1的对数,发现非常难以计算,我们转化问题考虑反面:哪些0不会对答案有贡献?不难发现只要连续的0两两配对都不会对答案有贡献,我们只需要用总数目减去这些不满足的即可。

状态表示:f(i,j,k)f_{(i,j,k)}f(i,j,k)​考虑前iii个位置,目前考虑了前jjj个111的位置,代价即交换次数是kkk的集合。
状态转移:考虑第j+1j+1j+1个111的位置,枚举i+1→ni+1\to ni+1→n,进行答案更新,这里是向后更新未知状态。

时间复杂度:O(n5)O(n^5)O(n5),但是常数非常小,再加上cf强大的评测鸡,跑的并不慢155ms

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int N=83,INF=0x3f3f3f3f;
int f[N][N][N*(N-1)/2];
int n,a[N],pos[N],cnt1;
int main()
{IO;int T=1;//cin>>T;while(T--){cin>>n;for(int i=1;i<=n;i++){cin>>a[i];if(a[i]) pos[++cnt1]=i;}int m=n*(n-1)/2;memset(f,0x3f,sizeof f);f[0][0][0]=0;for(int i=0;i<=n;i++)for(int j=0;j<cnt1;j++)for(int k=0;k<=m;k++){if(f[i][j][k]>=INF) continue;for(int p=i+1;p<=n;p++){int now=abs(p-pos[j+1]);if(now+k>m) continue;int cost=max(p-i-1,0)*max(p-i-2,0)/2;if(j+1==cnt1) cost+=(n-p)*(n-p-1)/2;f[p][j+1][k+now]=min(f[p][j+1][k+now],f[i][j][k]+cost);}}int cnt0=n-cnt1;for(int i=0;i<=m;i++){int res=INF;for(int j=1;j<=n;j++){if(i) f[j][cnt1][i]=min(f[j][cnt1][i],f[j][cnt1][i-1]);res=min(res,f[j][cnt1][i]);}if(!cnt1) cout<<0<<' ';else cout<<cnt0*(cnt0-1)/2-res<<' ';}}return 0;
}

Codeforces Round #672 (Div. 2)相关推荐

  1. Codeforces Round #672 (Div. 2)D. Rescue Nibel![扫描线解决区间问题]

    题目链接 题目大意:就是给你n个区间,从中选出k个区间,这k个区间共同覆盖了同一个点,问有多少种选法?结果mod 998244353 解题思路:1.首先我们可以这么想:我们把区间左端点赋值为1,右端点 ...

  2. 差分 ---- Codeforces Round #672 (Div. 2):C2. Pokémon Army (hard version)[差分的思想]

    题目链接 题目大意:就算给你一序列,按照顺序出若干个数组成一个的序列,然后对这个序列定义一个权值就算奇数位置的和减去偶数位置的和,问你能的到的最大的权值是多少? **a1 - a2 + a3 - a4 ...

  3. Codeforces Round #672 (Div. 2) C2 - Pokémon Army (hard version)(贪心,维护变化值)

    x数组里选一个子数组y(原数组顺序),y1-y2+y3-y4+- 的最大值 然后还有q次交换操作,每次修改之后都要输出新的最大值 (1)如果没有修改,单纯对于当前数组考虑,我们最后选出来的点肯定是波峰 ...

  4. Codeforces Round #672 (Div. 2) Pokémon Army

    题意就是给你一串数字,让你找出一串序列(可以不连续),使他们+,-,+,-...运算后这样的结果最大 比如 1 2 5 4 3 6 7 最大结果为5−3+7=9 hard version较easy v ...

  5. Codeforces Round #506 (Div. 3)

    Codeforces Round #506 (Div. 3) 实习期间事不多,对div3 面向题解和数据编程了一波 A. Many Equal Substrings 题目链接 A题就是找后缀和前缀重合 ...

  6. Codeforces Round #563 (Div. 2)/CF1174

    Codeforces Round #563 (Div. 2)/CF1174 CF1174A Ehab Fails to Be Thanos 其实就是要\(\sum\limits_{i=1}^n a_i ...

  7. 构造 Codeforces Round #302 (Div. 2) B Sea and Islands

    题目传送门 1 /* 2 题意:在n^n的海洋里是否有k块陆地 3 构造算法:按奇偶性来判断,k小于等于所有点数的一半,交叉输出L/S 4 输出完k个L后,之后全部输出S:) 5 5 10 的例子可以 ...

  8. Codeforces Round #696 (Div. 2) (A ~ E)超高质量题解(每日训练 Day.16 )

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Codeforces Round #696 (Div. 2) (A ~ E)超高质量题解 比赛链接:h ...

  9. Codeforces Round #712 Div.2(A ~ F) 超高质量题解(每日训练 Day.15 )

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Codeforces Round #712 Div.2(A ~ F) 题解 比赛链接:https:// ...

最新文章

  1. Python 技术篇-百度语音合成SDK接口调用演示
  2. 1080 两个数的平方和(数学)
  3. java 判断是否整形_java判断是否基本类型
  4. PAT_B_1012_Java(20分)
  5. linux重定向权限不够,linux – 如何使用sudo将输出重定向到一个我没有权限写入的位置?...
  6. 转---《C#画线控件的开发应用实例解析》
  7. 业余草最新热门博客推荐
  8. mysql5.7 jmeter_JMeter5连接Mysql数据库
  9. dnf强化卷代码_dnf强化卷叫什么名字?
  10. 最新 Hostinger域名转出教程 (2019年6月版本)
  11. Win10怎么设置自动锁屏? win10自动锁屏的两种方法
  12. 基于易班开放平台接入研究与探索
  13. 地图比例尺与空间分辨率之间的关系_航高、分辨率与比例尺的关系
  14. python爬虫:scrapy-redis分布式爬虫(详细版)
  15. 如何玩转抖音电商-基础篇
  16. Hudi Clean 清理文件实现分析
  17. Java Eclipse internal error Polling news feeds 解决方案
  18. 为什么新疆人吃的羊肉膻味那么重?
  19. 各种触发器(D、RS等)
  20. 齿轮数据接口标准及应用前景

热门文章

  1. .net html5页面缓存,详解HTML5中的manifest缓存使用
  2. re管理器Java_自定义布局管理器-FormLayout
  3. python设置字符间距_python字符串处理以及字符串格式化
  4. vspythonqt混合_PYQT5 vscode联合操作qtdesigner的方法
  5. 集合的定义与并查操作(C语言)
  6. [C语言] va_start和va_end详解
  7. C++map容器应用举例
  8. Servlet与线程安全
  9. Hills And Valleys CodeForces - 1467B 思维
  10. 【UOJ575】光伏元件【网络流建图】【上下界网络流】【费用流】