CF1239
然后ZUTTER_打的第一场div1以没敢交题 完!美!结!束!!!
A
没有发现性质就找规律海星
我们可以算出一列的贡献:\(g[i][0]\)表示上两个不同,\(g[i][1]\)表示上两个相同就可以互相转移,发现这是0项1项为2的斐波那契数列
有一个发现是如果上一列已经确定了,那么下一列可以和这一列一样或者完全相反其中有在这一列相邻两项都不同的情况下下一列才能与这一列完全相同,且不能有3列完全相同
然后只有2种情况下一列可以完全相同分别编号01也是不能有连续3个数字相同,同上是斐波那契数列
但是直接\(f[n]+f[m]\)还会有01010101和10101010会被算重再减掉2答案就是\(f[n]+f[m]-2\)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int f[400001],n,m;
const int P = 1e9+7;
int main()
{
scanf("%d%d",&n,&m);
f[0]=f[1]=2;
for(int i=2;i<=max(n,m);i++) f[i]=(f[i-1]+f[i-2])%P;
printf("%d",(f[n]+f[m]-2ll+P)%P);
}
B
观察怎样交换会比较优,如果交换并不配对的两个括号必不比交换配对的优
(的值是1,)的值是-1,求前缀和
发现如果已经交换了两个数序列的答案就是序列最小值的出现次数,感性理解一下就是\((....)(...)\)这样互不包含的括号组数
然后就可以做了
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<stack>
using namespace std;
const int M = 400001;
int n,m,k,a[M],b[M],d[M],mn=0x3f3f3f3f,w=0,s[3][M],pre[M],S[3],w0,w1,res=-1,pp[M];
char c[M];
stack<int> st;
void check(int x,int W0,int W1)
{
if(x>res) res=x, w0=W0, w1=W1;
}
int main()
{
scanf("%d\n%s",&n,c+1);
for(int i=1;i<=n;i++)
{
if(c[i]==')') a[i]=-1;
else a[i]=1;
d[i]=d[i-1]+a[i];
if(d[i]<mn) mn=d[i], w=i+1;
}
if(d[n]!=0)
{
printf("0\n1 1");
return 0;
}
for(int i=w;i<=n;i++)
{
b[++m]=a[i];
pp[m]=i;
}
for(int i=1;i<w;i++)
{
b[++m]=a[i];
pp[m]=i;
}
swap(b,a);
for(int i=1;i<=n;i++)
{
s[0][i]=s[0][i-1];
s[1][i]=s[1][i-1];
s[2][i]=s[2][i-1];
d[i]=d[i-1]+a[i];
if(d[i]==0) s[0][i]++;
if(d[i]==1) s[1][i]++;
if(d[i]==2) s[2][i]++;
}
res=s[0][n]; w1=w0=1;
for(int i=1;i<=n;i++)
{
if(a[i]==1) st.push(i);
else pre[i]=st.top(), st.pop();
}
for(int i=1;i<=n;i++)
{
if(!pre[i]) continue;
int p=pre[i];
S[0]=s[0][i-1]-s[0][p-1];
S[1]=s[1][i-1]-s[1][p-1];
S[2]=s[2][i-1]-s[2][p-1];
if(S[0]+S[1]+S[2]==0) continue;
if(!S[0] && !S[1]) check(S[2]+s[0][n],i,p);
else if(!S[0]) check(S[1],i,p);
else check(S[0],i,p);
}
printf("%d\n%d %d",res,min(pp[w0],pp[w1]),max(pp[w0],pp[w1]));
}
C
这题题意好奇怪啊qaq
如果a正在接水,这时\(b(b>a)\)想喝水,他会因为a不在座位上继续坐在座位上等,接着\(c(c<a)\) 又想喝水,他会去排队,所以接水序列acb
如果a正在接水,这时\(b(b<a)\)想喝水,他会去排队,接着\(c(c<a)\) 又想喝水,他也会去排队,所以接水序列abc
抽象一下就是维护一个队列和一个堆。按照想喝水时间和序号排序后如果下一个人的序号比队列里最后一个人还要小也就是说他的前面每个人都在座位上,他会去排队也就是加入队列;否则他会坐在座位上等到他前面的人都回来且正在等着去排队的人也喝完水才能去接水,把他加入堆
每次清空队列后把堆里的第一个人加入队列重复上面过程即可
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#define LL long long
using namespace std;
const int M = 200001;
priority_queue<int> p;
int n,m,k,ct,f[M];
LL rs[M],T;
struct vv
{
int t,id;
} a[M];
bool cmp(vv a,vv b){return (a.t==b.t)?a.id<b.id : a.t<b.t;}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i].t);
a[i].id=i; f[i]=a[i].t;
}
sort(a+1,a+1+n,cmp);
while(ct<n || p.size())
{
int ir;
if(p.size()) ir=-p.top(), p.pop(), T+=m;
else T=(LL)a[++ct].t+m,ir=a[ct].id;
rs[ir]=T;
while(ct<n && T>=a[ct+1].t)
{
++ct;
if(ir<a[ct].id) p.push(-a[ct].id);
else T+=m, rs[a[ct].id]=T, ir=a[ct].id;
}
}
for(int i=1;i<=n;i++) cout<<rs[i]<<' ';
}
D
这题到底是怎么混成div1的D的啊qaqaqaqaq
给定一个n个点的有向图,把n个点分成两组,要求没有第一组指向第二组的边
建一张图和一个反向边的图
如果1在第一组里那么1能连到的点都在第一组,但是如果1能连到整张图那么1就不能再第一组;如果1在第二组那么1在反图中连到的点都在第二组,如果能连满整张图无解
就这样
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int M = 2000001;
int n,m,k,ver[2][M],nex[2][M],head[2][M],cnt,T,x,y,vis[M],ct;
void add(int x,int y)
{
ver[0][++cnt]=y, nex[0][cnt]=head[0][x], head[0][x]=cnt;
ver[1][++cnt]=x, nex[1][cnt]=head[1][y], head[1][y]=cnt;
}
void dfs(int x,int k)
{
if(vis[x]) return ;
vis[x]=1, ct++;
for(int i=head[k][x];i;i=nex[k][i]) if(!vis[ver[k][i]])dfs(ver[k][i],k);
}
int main()
{
scanf("%d",&T);
for(;T;T--)
{
scanf("%d%d",&n,&m); ct=0; cnt=0;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
if(x!=y)add(x,y);
}
dfs(1,0);
if(ct==n)
{
for(int i=1;i<=n;i++) vis[i]=0;
ct=0;dfs(1,1);
if(ct==n) printf("No\n");
else
{
printf("Yes\n");
printf("%d %d\n",n-ct,ct);
for(int i=1;i<=n;i++) if(!vis[i]) printf("%d ",i);
printf("\n");
for(int i=1;i<=n;i++) if(vis[i]) printf("%d ",i);
printf("\n");
}
}
else
{
printf("Yes\n");
printf("%d %d\n",ct,n-ct);
for(int i=1;i<=n;i++) if(vis[i]) printf("%d ",i);
printf("\n");
for(int i=1;i<=n;i++) if(!vis[i]) printf("%d ",i);
printf("\n");
}
for(int i=1;i<=n;i++) vis[i]=0;
for(int i=1;i<=cnt;i++) nex[0][i]=nex[1][i]=0;
for(int i=1;i<=n;i++) head[0][i]=head[1][i]=0;
}
}
E
由于左上角和右下角必到,所以分别填最小值和次小值
考虑第一行剩下的值从小到大的填,第二行剩下的值从小到大的填
这样的话就可以保证不会在第1个和第n个位置之外的位置向下走
然后问题就变成把2n-2个数分成两组使差最小,背包即可
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define LL long long
using namespace std;
const int M = 2000001;
int n,m,k,a[M],S,d[3][M];
LL f[M][26];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n*2;i++) scanf("%d",&a[i]),S+=a[i];
sort(a+1,a+1+n+n); int s=0;
memset(f,-1,sizeof(f));
f[0][0]=0; S-=a[1]+a[2];
S/=2;
for(int i=3;i<=n+n;i++)
{
s+=a[i];
s=min(s,S);
for(int j=s;j>=a[i];j--)
for(int k=min(i-3,(n+n-2)/2);k>=0;k--)
if(f[j-a[i]][k]>=0) f[j][k+1]=f[j-a[i]][k]|(1ll<<i);
}
while(f[S][(n+n-2)/2]==-1) S--;
d[1][1]=a[1];
int ct=1;
LL k=f[S][(n+n-2)/2];
for(int i=3;i<=n+n;i++)
{
if(k&(1ll<<i)) d[1][++ct]=a[i];
}
d[2][n]=a[2];
ct=n;
for(int i=3;i<=n+n;i++)
{
if(!(k&(1ll<<i))) d[2][--ct]=a[i];
}
for(int i=1;i<=n;i++) printf("%d ",d[1][i]);
printf("\n");
for(int i=1;i<=n;i++) printf("%d ",d[2][i]);
}
CF1239的更多相关文章
- 在$CF$水题の记录
CF1158C CF1163E update after CF1173 很好,我!expert!掉rating了!! 成为pupil指日可待== 下次要记得合理安排时间== ps.一道题都没写的\(a ...
随机推荐
- fiddler 解决不能抓https包的问题
新解决方案 重置Fiddler,具体步骤: Tools > Fiddler Options > HTTPS > “Certificates generated by MakeCert ...
- javaIO流(四)--输入与输出支持
一.打印流 如果现在要想通过程序实现内容的输出,核心的本质一定要依靠OutputStream类来支持但是OutputStream类有一个最大的缺点,这个类的数据输出操作功能有限,所有的数据一定要转为字 ...
- Windows平台下在Emacs中使用plantuml中文乱码问题(已解决)
Windows平台下在Emacs中使用plantuml中文乱码问题(已解决) */--> code {color: #FF0000} pre.src {background-color: #00 ...
- 【目录】mysql 架构篇系列
随笔分类 - mysql 架构篇系列 mysql 架构篇系列 4 复制架构一主一从搭建(半同步复制) 摘要: 一.概述 在mysql 5.5之前,mysql 的复制是异步操作,主库和从库的数据之间存在 ...
- vue 实现active点击图片切换
循环条件下: 1.点击函数@click="active(index)" 获取点击的位置 2.讲索引值传给class,点击哪一个则显示哪一个的样式 3.在data添加ins的初始值 ...
- C# 交集 差集 并集
Intersect 交集,Except 差集,Union 并集 , , , , }; , , , , , }; var jiaoJi = oldArray.Intersect(newArray).To ...
- http请求访问响应慢问题解决的基本思路
第一步,检查网络 ping命令检查网络域名解析是否正常,ping服务器的延迟是否过大,如果过大可以检查Ip是否冲突,或者交换机网线是否正常插好,通过nmon还可以查看网络流量,一般用的千兆交换机理论速 ...
- 前端学习(二十六)移动端s(笔记)
===================================================弹性布局rem布局---------------------------------------- ...
- 虚拟机设置静态IP地址
前言 NAT连接方式只能配置一次,配置好子网掩码和网关IP后,虚拟机NAT连接的ip段都是同一个ip段 1.菜单栏选择 编辑 -> 虚拟网络编辑器,打开虚拟网络编辑器对话框,选择Vmnet8 N ...
- 字符串操作——C语言实现
代码如下: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <asse ...