CF1430
CF1430
那个博客搭好遥遥无期。
A:
看代码。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t;scanf("%d",&t);
while(t--)
{
int n;scanf("%d",&n);
if(n % 3 == 0)
{
printf("%d 0 0\n",n / 3);
}
if(n % 3 == 1)
{
if(n < 7)puts("-1");
else printf("%d 0 1\n",(n - 7) / 3);
}
if(n % 3 == 2)
{
if(n < 5)puts("-1");
else printf("%d 1 0\n",(n - 5) / 3);
}
}
return 0;
}
B:
显然把最大的几个都倒到一起最优。
#include<bits/stdc++.h>
using namespace std;
int n,k;
#define MAXN 200010
int a[MAXN];
void work()
{
scanf("%d%d",&n,&k);
for(int i = 1;i <= n;++i)scanf("%d",&a[i]);
sort(a + 1,a + 1 + n);
long long sum = 0;
for(int i = n,p = 1;i >= 1 && p <= k + 1;--i,++p)sum += a[i];
printf("%lld\n",sum);
return;
}
int main()
{
int testcases;
scanf("%d",&testcases);
while(testcases--)work();
return 0;
}
C:
最后一定削成 \(2\) ,按照样例的提示做就行了。
#include<bits/stdc++.h>
using namespace std;
int n;
void work()
{
scanf("%d",&n);
printf("2\n");
if(n == 2)
{
printf("1 2\n");
return;
}
printf("%d %d\n",n,n - 2);
printf("%d %d\n",n - 1,n - 1);
for(int i = n - 3;i >= 1;--i)printf("%d %d\n",i,i + 2);
return;
}
int main()
{
int testcases;scanf("%d",&testcases);
while(testcases--)work();
return 0;
}
D:
我们肯定是先找靠前的长度大于 \(1\) 的段删。
#include<bits/stdc++.h>
using namespace std;
int n;
#define MAXN 200010
int a[MAXN];
int getc()
{
char c = getchar();
while(!isdigit(c))c = getchar();
return c - '0';
}
struct seg{int v,l,p;}s[MAXN];
bool operator < (seg a,seg b){return a.p < b.p;}
int sn = 0;
set<seg> ss,sl;
void work()
{
scanf("%d",&n);
for(int i = 1;i <= n;++i)a[i] = getc();
sn = 0;
for(int i = 1;i <= n;++i)
{
if(i != 1 && a[i] == a[i - 1])++s[sn].l;
else s[++sn] = (seg){a[i],1,i};
}
int ans = 0;
ss.clear();sl.clear();
for(int i = 1;i <= sn;++i)ss.insert(s[i]);
for(int i = 1;i <= sn;++i)if(s[i].l > 1)sl.insert(s[i]);
while(!ss.empty())
{
++ans;
if(!sl.empty())
{
set<seg>::iterator it = sl.begin();
seg t = *it;sl.erase(it);
ss.erase(ss.find(t));
--t.l;
if(t.l > 1)sl.insert(t);
ss.insert(t);
}
else
{
set<seg>::iterator it = ss.begin();
ss.erase(*it);
}
if(!ss.empty())
{
set<seg>::iterator it = ss.begin();
seg t = *it;
ss.erase(*it);
if(t.l > 1)sl.erase(*it);
}
}
printf("%d\n",ans);
return;
}
int main()
{
int testcases;
scanf("%d",&testcases);
while(testcases--)work();
return 0;
}
E:
一定是一个一个一次移到最终位置最优,于是用树状数组统计前面还有多少个。
#include<bits/stdc++.h>
using namespace std;
int n;
#define MAXN 200010
char a[MAXN],r[MAXN];
char getc()
{
char c = getchar();
while(!islower(c))c = getchar();
return c;
}
deque<int> s[26];
int c[MAXN];
int lowbit(int x){return x & (-x);}
void add(int p,int x){for(int i = p;i <= n;i += lowbit(i))c[i] += x;return;}
int query(int p){int res = 0;for(int i = p;i >= 1;i -= lowbit(i))res += c[i];return res;}
int main()
{
scanf("%d",&n);
for(int i = 1;i <= n;++i)a[i] = getc();
for(int i = 1;i <= n;++i)s[a[i] - 'a'].push_back(i);
for(int i = 1;i <= n;++i)r[i] = a[n - i + 1];
for(int i = 1;i <= n;++i)add(i,1);
long long ans = 0;
for(int i = 1;i <= n;++i)
{
int pos = s[r[i] - 'a'].front();s[r[i] - 'a'].pop_front();
int fr = query(pos);
add(pos,-1);
ans += fr - 1;
}
cout << ans << endl;
return 0;
}
F:
好神啊,看了别人代码才会,直接做不好做,因为如果 \(r_i<l_{i+1}\) 那么每次可以直接丢掉,但是如果 \(r_i=l_{i+1}\) ,那么就不能在之间丢掉,就很不好处理,但是可以倒着做,这样就可以记录每次是不是一定会给上一轮剩下什么,就可以判断是否可行了。求最小值只要在保证能给下一次剩下足够的东西的前提下尽量不扔。因为只要能完成,这次能扔下次也能扔,所以尽量不扔一定优。不存在这次扔了能让下次少扔的情况,因为这样已经是能留下的最多的了。
#include<bits/stdc++.h>
using namespace std;
int n,k;
#define MAXN 2010
int l[MAXN],r[MAXN],a[MAXN];
long long rem[MAXN];
int main()
{
scanf("%d%d",&n,&k);
for(int i = 1;i <= n;++i)scanf("%d%d%d",&l[i],&r[i],&a[i]);
long long need = 0;
for(int i = n;i >= 1;--i)
{
need = a[i];
if(r[i] == l[i + 1])need += rem[i + 1];
if(need > 1ll * (r[i] - l[i] + 1) * k)
{
puts("-1");
return 0;
}
rem[i] = max(0ll,need - 1ll * (r[i] - l[i]) * k);
}
long long ans = 0,cur = 0;
for(int i = 1;i <= n;++i)
{
if(cur < rem[i])
{
ans += cur;
cur = k;
}
ans += a[i];
cur = (k - (a[i] - cur) % k) % k;
}
cout << ans << endl;
return 0;
}
G:
先化式子:
\]
然后我们一定是一层一层 \(DP\) 的,刚开始写了个记录层数的 \(DP\) 会 \(\text{T}\) ,之后发现可以每次给之前的都加 \(sumv\) 相当于是加了一层。
#include<bits/stdc++.h>
using namespace std;
int n,m;
#define MAXN 20
#define S 600000
long long sums[S];
long long f[S];
long long val[MAXN];
int ex[S];
struct edge
{
int to,nxt;
}e[MAXN * MAXN];
int edgenum = 0,lin[MAXN];
void add(int a,int b)
{
e[++edgenum] = (edge){b,lin[a]};lin[a] = edgenum;
return;
}
int pre[S];
int res[MAXN];
bool indep[S];
int main()
{//freopen("w.in","r",stdin);freopen("my.out","w",stdout);
scanf("%d%d",&n,&m);
int a,b,v;
for(int i = 1;i <= m;++i)
{
scanf("%d%d%d",&a,&b,&v);
val[a] += v;val[b] -= v;
add(a,b);
}//for(int i = 1;i <= n;++i)cout << val[i] << " ";cout << endl;
int tot = (1 << n) - 1;
for(int s = 0;s <= tot;++s)
{
for(int k = 1;k <= n;++k)
{
if(!(s & (1 << (k - 1))))continue;
for(int i = lin[k];i != 0;i = e[i].nxt)ex[s] |= (1 << (e[i].to - 1));
}
}
for(int s = 0;s <= tot;++s)
for(int k = 1;k <= n;++k)
if(s & (1 << (k - 1)))sums[s] += val[k];
memset(f,0x3f,sizeof(f));
for(int s = 0;s <= tot;++s)
{
indep[s] = true;
for(int k = 1;k <= n && indep[s];++k)
if(s & (1 << (k - 1)))
for(int i = lin[k];i != 0 && indep[s];i = e[i].nxt)
if(s & (1 << (e[i].to - 1)))indep[s] = false;
}
for(int s = 0;s <= tot;++s)if(indep[s])f[s] = sums[s];
for(int s = 0;s <= tot;++s)
{
int expand = tot ^ s;
for(int k = expand;k != 0;k = (k - 1) & expand)
{
if(!indep[k])continue;
if(ex[k] & s)continue;
if(f[s] + sums[s | k] < f[s | k])
{
f[s | k] = f[s] + sums[s | k];
pre[s | k] = s;
}
}
}//for(int s = 0;s <= tot;++s)cout << s << " - " << pre[s] << " " << f[s] << endl;
for(int cur = tot,i = 1;cur != 0;cur = pre[cur],++i)
{
int lay = cur ^ pre[cur];
for(int k = 1;k <= n;++k)if(lay & (1 << (k - 1)))res[k] = i;
}
for(int i = 1;i <= n;++i)printf("%d ",res[i]);puts("");
return 0;
}
CF1430的更多相关文章
- CF1430 E. String Reversal(div 2)
题目链接:http://codeforces.com/contest/1430/problem/E 题意:有一串长度为n(n<=2*10^5)由小写字母组成的字符串,求通过相邻交换得到其反转串( ...
- CF1430 D. String Deletion(div 2)
题目链接:http://codeforces.com/contest/1430/problem/D 题意:有一个长度为n(n<=2*10^5)的01字符串,每轮操作有两步: 第一步是删去字符串中 ...
随机推荐
- about namespace
once you specify to use a certain namespace such as "{using namespace1;...}", you need to ...
- Websocket(websocket自定义协议)
是基于TCP的 tcp特征: 我发数据对端可以接收到,对端发数据我可以收到 先发先收到,后发后收到 使用websocket客户端发给服务器数据,服务器回客户端返回数据流程(自定义websocket协议 ...
- 你对USB了解吗?--USB 协议分析之 HID 设备
1. 简述 USB HID类是USB设备的一个标准设备类,包括的设备非常多.HID类设备定义它属于人机交互操作的设备,用于控制计算机操作的一些方面,如USB鼠标.USB键盘.USB游戏操纵杆等.但HI ...
- Access denied You do not have access to chat.openai.com. The site owner may have set restrictions that prevent you from accessing the site.解决办法
报错 Access denied You do not have access to chat.openai.com. The site owner may have set restrictions ...
- kibana启动及导出PDF报错
kibana启动及导出PDF报错,可能是由于kibana需要的系统依赖没有安装 CentOS/RHEL系统需要安装以下依赖: ipa-gothic-fonts xorg-x11-fonts-100dp ...
- shell脚本操作mysql通用脚本
作用:可以在写监控脚本时,将结果值保存到mysql数据库 使用方法:sh 脚本 库名称.表名称 字段=值 字段=值 字段=值 1.脚本 [root@localhost tmp]# cat writ_ ...
- vue 打开页面触发事件
vue中created(),mounted()与activated()区别及应用 created():在创建vue对象时,当html渲染之前就触发:但是注意,全局vue.js不强制刷新或者重启时只创建 ...
- linux改变用户属主
将test文件的属主改为root:sudo chown root test 改变所在组:sudo chgrp root test 同时改变属主和所在组:sudo chown root.root tes ...
- JS篇(008)-require 与 import 的区别
答案:两者的加载方式不同.规范不同 第一.两者的加载方式不同,require 是在运行时加载,而 import 是在编译时加载 require('./a')(); // a 模块是一个函数,立即执行 ...
- hadoop单机测试环境安装(简)
1.下载hadoop官网就可以下载.可以直接搜hadoop , 其实可以直接查看官网的版主文档搭建https://hadoop.apache.org/docs/stable/hadoop-proj ...