CF1209

A B

水题不管

C

因为要求最终整个序列是要单调的

所以我们就考虑枚举断点\(x\)

之后把\(<x\)的数放到第一个集合

把\(> x\)的数放到第二个集合

至于\(=x\)的数

他能放到第一个集合当且仅当后面没有\(<x\)的数

否则就必须放到第二个集合

在放的时候判断合法性即可

(枚举把\(0-9\)写成了\(1 - 10\)就没了QAQ

#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<vector>
#include<ctime>
#include<cmath>
#define LL long long
#define pii pair<int,int>
#define mk make_pair
#define fi first
#define se second
using namespace std;
const int N = 5e5 + 3;
char s[N];
int a[N];
int sum[N][11];
int belong[N];
int n;
inline int read(){
int v = 0,c = 1;char ch = getchar();
while(!isdigit(ch)){
if(ch == '-') c = -1;
ch = getchar();
}
while(isdigit(ch)){
v = v * 10 + ch - 48;
ch = getchar();
}
return v * c;
}
inline bool check(int x){
// printf("x::%d\n",x);
int now1 = -1,now2 = -1;
for(int i = 1;i <= n;++i){
// printf("%d %d %d\n",i,now1,now2);
if(a[i] < x && a[i] < now1) return 0;
if(a[i] > x && a[i] < now2) return 0;
if(a[i] != x){
if(a[i] < x) now1 = max(now1,a[i]),belong[i] = 1;
else if(a[i] > x) now2 = max(now2,a[i]),belong[i] = 2;
}
if(a[i] == x){
bool flag = 0;
for(int j = 0;j <= x - 1;++j) if(sum[i][j]) flag = 1;
if((!flag) && (a[i] >= now1)) {
now1 = a[i],belong[i] = 1;
}
else{
if(now2 > a[i]) return 0;
now2 = max(now2,a[i]),belong[i] = 2;
}
}
}
return 1;
}
int main(){
int T = read();
while(T--){
bool flag = 0;
n = read();
scanf("%s",s + 1);
for(int i = 1;i <= n;++i) a[i] = s[i] - '0';
for(int i = n;i >= 1;--i){
for(int j = 0;j <= 9;++j) sum[i][j] = sum[i + 1][j];
sum[i][a[i]]++;
}
for(int i = 0;i <= 9;++i){
if(check(i)){
for(int j = 1;j <= n;++j) printf("%d",belong[j]);
printf("\n");
flag = 1;
break;
}
}
if(!flag) printf("-\n");
for(int i = 1;i <= n;++i){
for(int j = 0;j <= 9;++j) sum[i][j] = 0;
}
}
return 0;
}
 

D

首先我们发现把\(a_i\)向\(b_i\)连边最后会形成若干个连通块

每个连通块的大小 - 1就是这个连通块的贡献

#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<vector>
#include<ctime>
#include<cmath>
#define LL long long
#define pii pair<int,int>
#define mk make_pair
#define fi first
#define se second
using namespace std;
const int N = 5e5 + 3;
struct node{
int ai;
int bi;
}a[N];
vector <int> G[N];
int n,k;
bool flag1[N],flag2[N]; inline int read(){
int v = 0,c = 1;char ch = getchar();
while(!isdigit(ch)){
if(ch == '-') c = -1;
ch = getchar();
}
while(isdigit(ch)){
v = v * 10 + ch - 48;
ch = getchar();
}
return v * c;
}
queue <int> q;
int ans = 0;
inline void dfs(int x){
flag1[x] = 1;ans++;
for(int i = 0;i < (int)G[x].size();++i){
int y = G[x][i];
if(!flag1[y]) dfs(y);
}
}
int main(){
n = read(),k = read();
for(int i = 1;i <= k;++i){
a[i].ai = read();
a[i].bi = read();
G[a[i].ai].push_back(a[i].bi);
G[a[i].bi].push_back(a[i].ai);
}
for(int i = 1;i <= n;++i) if(!flag1[i]) ans--,dfs(i);
cout << k - ans;
}

E1E2

首先观察发现\(n\)特别小,当一个数小于等于\(20\)的时候第一反应就是要考虑状压

一个特别重要的性质

我们把所有的列按照这一列的最大值从大到小跑徐之后

最多只有前\(n\)列有用

也就是说

$n\times m \(的矩阵变成了\)n \times n$的

我们设\(f_{i,S}\)表示前\(i\)列,\(S\)这个状态对应的行的最大值已经确定的最大贡献,

\(g_{i,S}\)表示从第\(i\)列取出能够表示\(S\)这个集合的最大值

转移

\[f_{i,S} = \max_{T\subseteq S} f_{i - 1,S - T}+g_{i,T}
\]

记下来考虑怎么求\(g\)

由于存在轮换的存在

我们枚举一个集合,然后把这个集合能够表示的所有的状态都尝试用这个集合的值去更新

比如

\(1101\)能够表示\(1101\),\(1110\),\(1011\),\(0111\)

#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<vector>
#include<ctime>
#include<cmath>
#define LL long long
#define pii pair<int,int>
#define mk make_pair
#define fi first
#define se second
using namespace std;
const int M = 21;
const int N = 2003;
int a[M][N];
int b[M][M];
int n,m;
int f[13][(1 << 13) + 5];
int g[13][(1 << 13) + 3];
struct node{
int maxx;
int id;
}row[N];
inline bool cmp(node x,node y){
return x.maxx > y.maxx;
}
inline int read(){
int v = 0,c = 1;char ch = getchar();
while(!isdigit(ch)){
if(ch == '-') c = -1;
ch = getchar();
}
while(isdigit(ch)){
v = v * 10 + ch - 48;
ch = getchar();
}
return v * c;
}
int main(){
int T = read();
while(T--){
memset(g,0,sizeof(g));
memset(f,0,sizeof(f));
memset(row,0,sizeof(row));
n = read(),m = read();
for(int i = 1;i <= n;++i){
for(int j = 1;j <= m;++j){
a[i][j] = read();
row[j].maxx = max(row[j].maxx,a[i][j]);
row[j].id = j;
}
}
sort(row + 1,row + m + 1,cmp);
m = min(n,m);
for(int i = 1;i <= n;++i){
for(int j = 1;j <= m;++j)
b[i][j] = a[i][row[j].id];
}
for(int j = 1;j <= m;++j){
for(int i = 1;i < (1 << n);++i){
int res = i;
int sum = 0;
for(int h = 0;h < n;++h) if(res & (1 << h)) sum += b[h + 1][j];
for(int k = 0;k < n;++k){
g[j][res] = max(g[j][res],sum);
int nn = res;
res = ((nn >> (n - 1)) & 1) | ((nn << 1) & ((1 << n) - 1));
}
}
}
for(int i = 0;i < m;++i){
for(int j = 0;j < (1 << n);++j){
int S = ((1 << n) - 1) ^ j;
f[i + 1][j] = max(f[i + 1][j],f[i][j]);
for(int son = S;son;son = (son - 1) & S){
f[i + 1][j | son] = max(f[i + 1][j | son],f[i][j] + g[i + 1][son]);
}
}
}
printf("%d\n",f[m][(1 << n) - 1]);
}
return 0;
}

G1

我们发现,如果存在这种东西

3 1 3 1 3

那么整个区间最终都会是同一个数

也就是说

我们设\(l_i\)表示\(i\)的第一次出现的位置,\(r_i\)表示\(i\)最后一次出现的位置

最后会出现这种情况

我们发现有交集的区间最终都会变成同一个数,变成那个数取决于这个区间中那个数出现次数最多

我们把所有的区间搞出跑一跑贪心

#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<vector>
#include<ctime>
#include<cmath>
#define LL long long
#define pii pair<int,int>
#define mk make_pair
#define fi first
#define se second
using namespace std;
const int N = 5e5 + 3;
int a[N];
int fir[N],las[N];
int sum[N];
int n,q;
bool flag1 = 1,flag2 = 1;
inline int read(){
int v = 0,c = 1;char ch = getchar();
while(!isdigit(ch)){
if(ch == '-') c = -1;
ch = getchar();
}
while(isdigit(ch)){
v = v * 10 + ch - 48;
ch = getchar();
}
return v * c;
}
int ans = 0x3f3f3f3f;
struct node{
int li;
int ri;
int id;
};
vector <node> G;
inline bool cmp(node x,node y){
return x.li < y.li || (x.li == y.li && x.ri > y.ri);
}
int main(){
n = read(),q = read();
for(int i = 1;i <= n;++i){
a[i] = read();
if(!fir[a[i]]) fir[a[i]] = i;
las[a[i]] = i;
sum[a[i]]++;
}
for(int i = 1;i <= 200000;++i){
if(!fir[i]) continue;
if(!las[i]) G.push_back((node){fir[i],fir[i],i});
else G.push_back((node){fir[i],las[i],i});
}
sort(G.begin(),G.end(),cmp);
int ans = 0;
int now = 0;
int nowr = -1;
int len = 0;
int from = 1;
int maxx = 0;
// for(int i = 0;i < (int)G.size();++i){
// printf("%d %d %d\n",G[i].id,G[i].li,G[i].ri);
// }
while(now < G.size()){
if(G[now].li > nowr){
ans += nowr - from + 1 - maxx;
from = nowr + 1;
maxx = 0;
maxx = max(maxx,sum[G[now].id]);
nowr = G[now].ri;
}
else{
nowr = max(nowr,G[now].ri);
maxx = max(maxx,sum[G[now].id]);
}
now++;
}
ans += nowr - from + 1 - maxx;
printf("%d\n",ans);
return 0;
}
 

CF1209的更多相关文章

  1. CF1209题解

    E 每列都可以沿下滚动若干次,使得各行最大值之和最大 对每列的元素计算最大值,降序排,显然取前\(min(n,m)\)个列处理即可 比较巧妙的动规,设\(f(i,S)\)为前\(i\)列,已经确定最大 ...

随机推荐

  1. oracle-Expdp/impdp命令

    建立逻辑路径 create or replace directory dumpdir as 'c:\'; grant read,write on directory dumpdir to scott; ...

  2. C++临时对象的生命期

    class Test{ public: Test(int a):m_int(a){ printf("this is Test(%d) ctor\n", m_int); } ~Tes ...

  3. 【JZOJ4847】【NOIP2016提高A组集训第5场11.2】夕阳

    题目描述 "我有个愿望,我希望在灿烂千阳时遇见你." 这是个有n个点的世界,有m条无向边连接着这n个点,但是不保证点之间能够互相到达. "这个世界的夕阳,只在奇数长的简单 ...

  4. 【JZOJ4820】【NOIP2016提高A组模拟10.15】最大化

    题目描述 输入 输出 样例输入 3 2 4 0 -10 8 -2 -2 样例输出 4 数据范围 解法 枚举两条扫描线,在这两条扫描线之间的矩阵,可以将之转化为一个序列b[i]=a[i][1..m]. ...

  5. DirectX11 With Windows SDK--07 添加光照与常用几何模型、光栅化状态

    原文:DirectX11 With Windows SDK--07 添加光照与常用几何模型.光栅化状态 前言 对于3D游戏来说,合理的光照可以让游戏显得更加真实.接下来会介绍光照的各种分量,以及常见的 ...

  6. Python traceback模块简单使用

    Python中的traceback模块被用于跟踪异常返回信息,可以在logging中记录下traceback. traceback.format_exc() 获取异常为字符串,保存到日志文件 try: ...

  7. 2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛 H Skiing【拓扑排序,关键路径】

    2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛  H Skiing In this winter holiday, Bob has a plan for skiing at the moun ...

  8. TensorFlow的 卷积层

    用 TensorFlow 做卷积 让我们用所学知识在 TensorFlow 里构建真的 CNNs.在下面的练习中,你需要设定卷积核滤波器(filters)的维度,weight,bias.这在很大程度上 ...

  9. E. Remainder Problem 分块

    两个操作 1对x位置的a[x]+y 2对所有i=y(mod x)求a[i]的和 我们肯定不能n^2 跑,稳超时,但是我们可以这样分块考虑. 为什么n^2不行?因为在x比较小的时候,这个求和操作次数太多 ...

  10. Android Studio(一):介绍、安装、配置

    Android Studio相关博客: Android Studio(一):介绍.安装.配置 Android Studio(二):快捷键设置.插件安装 Android Studio(三):设置Andr ...