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:

先化式子:

\[\sum_{i=1}^mw_i\times(a_{x_i}-a_{y_i})=\sum_{i=1}^na_i\times (outs[i]-ins[i])
\]

然后我们一定是一层一层 \(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的更多相关文章

  1. CF1430 E. String Reversal(div 2)

    题目链接:http://codeforces.com/contest/1430/problem/E 题意:有一串长度为n(n<=2*10^5)由小写字母组成的字符串,求通过相邻交换得到其反转串( ...

  2. CF1430 D. String Deletion(div 2)

    题目链接:http://codeforces.com/contest/1430/problem/D 题意:有一个长度为n(n<=2*10^5)的01字符串,每轮操作有两步: 第一步是删去字符串中 ...

随机推荐

  1. Jupyter Notebook安装代码提示功能

    默认Jupyter Notebook没有安装代码提示功能,但是我们可以可通过如下命令安装和配置使得Jupyter Notebook具备代码提供功能. (确保Anaconda在环境变量里)1.电脑上搜索 ...

  2. 微信h5支付报错 商家参数格式有误,请联系商家解决

    商家参数格式有误,请联系商家解决 当前调起H5支付的referer为空导致,一般是因为直接访问页面调起H5支付,请按正常流程进行页面跳转后发起支付,或自行抓包确认referer值是否为空 解决:就把 ...

  3. C#中的ReferenceEquals、Equals以及==

    https://www.cnblogs.com/ArtofDesign/p/3615212.html   C#中有一共有四种相等性判断方法: //Object中定义的三个方法 public stati ...

  4. ASP.NET Core Web API通过中间件或UseExceptionHandler异常处理方法

    UseExceptionHandler app.UseExceptionHandler(configure => { configure.Run(async context => { va ...

  5. stream 链式结构 求和

    Double aDouble = Optional.ofNullable(wayfairMonthBill.getPaymentAmountDetailJson()) .filter(StringUt ...

  6. 3.Linux安装docker

    Docker作为一个软件集装箱化平台,可以让开发者构建应用程序时,将它与其依赖环境一起打包到一个容器中,然后很容易地发布和应用到任意平台中. 进入docker官网找到安装文档 https://docs ...

  7. Solution - ARC152D Halftree

    首先 \(n\) 为偶数时无解,这是显然的,因为一次加两条边,总边数一定是偶数. 下面我们证明 \(n\) 为奇数时一定有解,直接进行构造. 首先将每一个点编号加上 \(k\) 再模 \(n\) 的答 ...

  8. JS中有关(...)的介绍

    1,深拷贝一个对象 如上图所示,obj和tmp是完全两个独立的对象,互不影响. 2,数组复制 如上图所示,arr和tmp是两个完全独立的数组,彼此之间的值互不影响. 3,函数形参中的使用 这里的... ...

  9. 044_Schedule Job 间隔时间自动执行

    需求:系统上的标准功能是能够设置间隔一天的执行,或者是写完代码着急测试我们写个5分钟后执行的: 但是遇到要求没间隔一小时或者十分钟执行,该怎么处理呢? global class **_Retrieve ...

  10. 在安装SDK8.1和Visual Studio 2017时,提示“已停止工作”

    解决办法:在微软官网下载 .net framework 的最新的开发包(Build apps - Dev Pack),重新安装后问题得到解决. https://dotnet.microsoft.com ...