Codeforces Round #402 (Div. 1)
A题卡壳了,往离线倒着加那方面想了会儿,后来才发现方向错了,二十多分钟才过掉,过了B后做D,想法好像有点问题,最后只过两题,掉分了,差一点回紫。
AC:AB Rank:173 Rating:2227-23->2204
A.String Game
题目大意:给出字符串A和B,保证B是A的子序列,给出一个长度为A串长度的排列,问按排列的顺序删掉A串中字符,最多删几个使得B任然是A的子序列。(A串长度<=200,000)
思路:发现答案满足单调性,二分删几个,O(n)check一下B还是不是A的子序列,复杂度O(nlogn)。
#include<cstdio>
inline int read()
{
int x;char c;
while((c=getchar())<''||c>'');
for(x=c-'';(c=getchar())>=''&&c<='';)x=(x<<)+(x<<)+c-'';
return x;
}
#define MN 200000
char a[MN+],b[MN+],s[MN+];
int p[MN+];
bool check(int x)
{
int i,j;
for(i=;a[i];++i)s[i]=a[i];
for(i=;i<x;++i)s[p[i]-]=' ';
for(i=j=;s[i]&&b[j];++i)if(s[i]==b[j])++j;
return !b[j];
}
int main()
{
int i,l=,r,mid,ans;
scanf("%s%s",a,b);
for(r=;a[r];++r)p[r]=read();
while(l<=r)
{
mid=l+r>>;
if(check(mid))ans=mid,l=mid+;
else r=mid-;
}
printf("%d",ans);
}
B.Bitwise Formula
题目大意:给出n条语句和语句中数字的二进制串长m,每条语句会新定义一个变量,并给它赋值,赋值语句有两种,一种给出一个长为m的二进制常量,另一种给出两个出现过的变量或"?",以及一个位运算符(AND、OR、XOR)。所有"?"可以用同一个长为m的二进制串代替,问这个串最小为多少时,所有变量的和最大/最小。(N<=5000,M<=1000)
思路:二进制的每一位独立,分别枚举取0取1就可以了,复杂度O(nm)。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
inline int read()
{
int x;char c;
while((c=getchar())<''||c>'');
for(x=c-'';(c=getchar())>=''&&c<='';)x=(x<<)+(x<<)+c-'';
return x;
}
#define MN 5000
#define MM 1000
map<string,int> mp;
int n,a[MN+][MM+],cnt;
int t[MN+],ta[MN+],tb[MN+];
int aa[MM+],bb[MM+];
int f[MN+];
int check(int p,int k)
{
int i,s=;
for(i=;i<=n;++i)
{
if(!t[i])f[i]=a[i][p];
if(t[i]==)f[i]=(ta[i]?f[ta[i]]:k)&(tb[i]?f[tb[i]]:k);
if(t[i]==)f[i]=(ta[i]?f[ta[i]]:k)|(tb[i]?f[tb[i]]:k);
if(t[i]==)f[i]=(ta[i]?f[ta[i]]:k)^(tb[i]?f[tb[i]]:k);
s+=f[i];
}
return s;
}
int main()
{
int m,i,j,x,y;string s;
n=read();m=read();
for(i=;i<=n;++i)
{
cin>>s;mp[s]=++cnt;cin>>s;
cin>>s;
if(s[]==''||s[]=='')
{
for(j=;j<m;++j)a[i][j]=s[j]-'';
continue;
}
ta[i]=s[]=='?'?:mp[s];
cin>>s;
if(s[]=='A')t[i]=;
if(s[]=='O')t[i]=;
if(s[]=='X')t[i]=;
cin>>s;
tb[i]=s[]=='?'?:mp[s];
}
for(i=;i<m;++i)
{
x=check(i,);y=check(i,);
aa[i]=y<x;bb[i]=y>x;
}
for(i=;i<m;++i)printf("%d",aa[i]);puts("");
for(i=;i<m;++i)printf("%d",bb[i]);
}
C.Peterson Polyglot
题目大意:给出一棵n个节点的Trie树,可以选择一个p,删除Trie树各节点表示的字符串中第p个字符后再组成一棵新的Trie树,求新Trie树的最少节点数和此时应选的最小的p。(n<=300,000)
思路:对树上每个节点统计以该节点深度(根为1)作为p时这棵子树对答案的贡献,贡献即为以该节点各儿子为根的子树合并成一个的大小减去以这个节点为根的子树的大小。合并我们可以用可持久化思想,直接建新的点连向原树,这样两棵子树合并,最多新建相当于小的子树的大小的节点,发现复杂度与启发式合并整棵Trie树相同。总复杂度O(26nlogn)(常数较小)。
#include<cstdio>
inline int read()
{
int x;char c;
while((c=getchar())<''||c>'');
for(x=c-'';(c=getchar())>=''&&c<='';)x=(x<<)+(x<<)+c-'';
return x;
}
#define MN 600000
int n,c[MN+][],f[MN+],cnt,tn;
int merge(int x,int y)
{
if(!x)return y;if(!y)return x;
int r=++tn;++cnt;
for(int i=;i<;++i)c[r][i]=merge(c[x][i],c[y][i]);
return r;
}
void dfs(int x,int d)
{
int i,rt=++(tn=n);cnt=;
for(i=;i<;++i)if(c[x][i])rt=merge(rt,c[x][i]);
f[d]+=cnt;
for(i=;i<;++i)if(c[x][i])dfs(c[x][i],d+);
}
int main()
{
int i,x,y;
for(n=read(),i=;i<n;++i)x=read(),y=read(),c[x][getchar()-'a']=y;
dfs(,);
for(i=,x=;i<=n;++i)if(f[i]>x)x=f[i],y=i;
printf("%d\n%d",n-x,y);
}
D.Parquet Re-laying
题目大意:给出一个n*m的棋盘,和两个覆盖满1*2棋子的状态,每次允许把相邻两个摆向相同的棋子旋转90°,要求构造出不超过100,000步的方案从一个状态转成另一个状态,无解输出-1。(n,m<=50)
思路:每次从上到下,从左到右找到能旋的横着的棋子,全部转为竖着;再每次找到竖着的棋子转为横着,可以证明最后一定后转成全为横或全为竖,把两个状态都这样做一遍再把第二个的操作反过来输出就可以了。复杂度O(能过)。
#include<cstdio>
#define MN 50
#define MK 100000
char s[MN+][MN+];
int n,m,x[MK+],y[MK+],xn,cnt,t,k[];
void solve()
{
int i,j;
for(i=k[t]=;i<n;++i)
{
scanf("%s",s[i]);
for(j=;j<m;++j)++k[s[i][j]];
}
while(k[t])
{
for(i=;i<n;++i)for(j=;j<m;++j)if(s[i][j]=='U'&&s[i][j+]=='U')
x[++cnt]=i+,y[cnt]=j+,s[i][j]=s[i+][j]='L',s[i][j+]='R',k['U']-=,k['L']+=;
if(!k[t])return;
for(i=;i<n;++i)for(j=;j<m;++j)if(s[i][j]=='L'&&s[i+][j]=='L')
x[++cnt]=i+,y[cnt]=j+,s[i][j]=s[i][j+]='U',s[i+][j]='D',k['U']+=,k['L']-=;
}
}
int main()
{
scanf("%d%d",&n,&m);
t=n&?'U':'L';
solve();xn=cnt;
solve();printf("%d\n",cnt);
for(int i=;i<=xn;++i)printf("%d %d\n",x[i],y[i]);
for(int i=cnt;i>xn;--i)printf("%d %d\n",x[i],y[i]);
}
E.Selling Numbers
题目大意:给一个由数字和"?"组成的串,你可以用0~9替换"?",组成一个数,但要求这个数首位不能为0,给你n个数,把这n个数都分别加上你选出的数,给出0~9各个数字的权值,要求最后n个数中各个出现的数字的权值和加起来最大,求出这个值。(出现的数字和串都不超过1000位,n<=1000)
思路:考虑数位DP,从末尾往前推,每一位的状态只与后一位是否进位有关,发现若把每个数字当前处理过的部分拿出来排个序,进位的数是连续的,用f[i][j]表示当前处理到第i位,每个数后i位从大到小排序后前j个有进位时的最大权值和,每次枚举当前串选哪个数字就能转移了,排序的方法可以以第i位为第1关键字,后i-1位的大小顺序为第2关键字进行计数排序,再注意下一些实现细节就可以了。总复杂度O(10nL)(L表示数和串的长度)。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MN 1001
char a[MN+],b[MN+][MN+],s[MN+];
int l[MN+],f[MN+][MN+],g[MN+][MN+],sa[MN+][MN+],c[MN+],ss[];
void read(char*a,int p)
{
scanf("%s",s);
while(s[l[p]])++l[p];
for(int i=;s[i];++i)a[l[p]-i]=s[i];
}
int get(int x,int y){return b[x][y]?b[x][y]-'':;}
int value(int x,int y){return y>max(l[x],l[])&&!g[x][y]?:c[g[x][y]];}
int main()
{
int n,i,j,k,r,p,v;
read(a,);scanf("%d",&n);
for(i=;i<=n;++i)read(b[i],i);
for(i=;i<;++i)scanf("%d",&c[i]);
for(i=;i<=n;++i)sa[][i]=i;
memset(f,,sizeof(f));f[][]=;
for(i=;i<=MN;++i)
{
memset(ss,,sizeof(ss));
for(j=;j<=n;++j)++ss[get(j,i)];
for(j=;j;--j)ss[j-]+=ss[j];
for(j=n;j;--j)sa[i][ss[get(sa[i-][j],i)]--]=sa[i-][j];
if(i>l[])j=r=;
else if(a[i]=='?')j=i==l[],r=;
else j=r=a[i]-'';
for(;j<=r;++j)
{
for(p=v=,k=;k<=n;++k)
{
g[k][i]=get(k,i)+j;
if(g[k][i]>)g[k][i]-=,++p;
v+=value(k,i);
}
for(k=;;)
{
f[i][p]=max(f[i][p],f[i-][k]+v);
if(k++==n)break;
v-=value(sa[i-][k],i);
if(++g[sa[i-][k]][i]>)g[sa[i-][k]][i]=,++p;
v+=value(sa[i-][k],i);
}
}
}
printf("%d",f[MN][]);
}
Codeforces Round #402 (Div. 1)的更多相关文章
- Codeforces Round #402 (Div. 2)
Codeforces Round #402 (Div. 2) A. 日常沙比提 #include<iostream> #include<cstdio> #include< ...
- Codeforces Round #402 (Div. 2) A+B+C+D
Codeforces Round #402 (Div. 2) A. Pupils Redistribution 模拟大法好.两个数列分别含有n个数x(1<=x<=5) .现在要求交换一些数 ...
- Codeforces Round #402 (Div. 2) A,B,C,D,E
A. Pupils Redistribution time limit per test 1 second memory limit per test 256 megabytes input stan ...
- Codeforces Round #402 (Div. 2) D. String Game
D. String Game time limit per test 2 seconds memory limit per test 512 megabytes input standard inpu ...
- Codeforces Round #402 (Div. 2) A B C sort D二分 (水)
A. Pupils Redistribution time limit per test 1 second memory limit per test 256 megabytes input stan ...
- 【DFS】Codeforces Round #402 (Div. 2) B. Weird Rounding
暴搜 #include<cstdio> #include<algorithm> using namespace std; int n,K,Div=1,a[21],m,ans=1 ...
- Codeforces Round #402 (Div. 2) 题解
Problem A: 题目大意: 给定两个数列\(a,b\),一次操作可以交换分别\(a,b\)数列中的任意一对数.求最少的交换次数使得任意一个数都在两个序列中出现相同的次数. (\(1 \leq a ...
- Codeforces Round #402 (Div. 2) 阵亡记
好长时间没有打Codeforces了,今天被ysf拉过去打了一场. lrd也来参(nian)加(ya)比(zhong)赛(sheng) Problem A: 我去,这不SB题吗.. 用桶统计一下每个数 ...
- CodeForces Round #402 (Div.2) A-E
2017.2.26 CF D2 402 这次状态还算能忍吧……一路不紧不慢切了前ABC(不紧不慢已经是在作死了),卡在D,然后跑去看E和F——卧槽怎么还有F,早知道前面做快点了…… F看了看,不会,弃 ...
- Codeforces Round #402 (Div. 2) B
Description Polycarp is crazy about round numbers. He especially likes the numbers divisible by 10k. ...
随机推荐
- 1013团队Beta冲刺day4
项目进展 李明皇 今天解决的进度 因服务器端未完成登录态维护,故无法进行前后端联动. 明天安排 前后端联动调试 林翔 今天解决的进度 因上课和实验室事务未完成登录态维护 明天安排 完成登录态维护 孙敏 ...
- 关于使用栈将一般运算式翻译为后缀表达式并实现三级运算的方法及实例(cpp版)
#include <iostream> #include <stack> #include <vector> #include <string> #de ...
- (原创)不带模板的OLE输出EXCEL
目前我已知的EXCEL输出方式有3种: 1.GUI_DOWNLOAD函数输出(适用于简单无格式要求的输出). 2.OLE输出(适用于对EXCEL格式输出有特殊要求的,但是因其填充数据和设置格式是基于一 ...
- day-4 python多进程编程知识点汇总
1. python多进程简介 由于Python设计的限制(我说的是咱们常用的CPython).最多只能用满1个CPU核心.Python提供了非常好用的多进程包multiprocessing,他提供了一 ...
- NYOJ 炫舞家st
#include <iostream>#include <cstring>#include <algorithm>using namespace std; cons ...
- ASP.NET Web API编程——路由
路由过程大致分为三个阶段: 1)请求URI匹配已存在路由模板 2)选择控制器 3)选择操作 1匹配已存在的路由模板 路由模板 在WebApiConfig.Register方法中定义路由,例如模板默认生 ...
- vscode使用shell
https://stackoverflow.com/questions/42606837/how-to-use-bash-on-windows-from-visual-studio-code-inte ...
- 回收 PV - 每天5分钟玩转 Docker 容器技术(152)
当 PV 不再需要时,可通过删除 PVC 回收. 当 PVC mypvc1 被删除后,我们发现 Kubernetes 启动了一个新 Pod recycler-for-mypv1,这个 Pod 的作用就 ...
- 新概念英语(1-139)Is that you, John?
Lesson 139 Is that you, John? 是你吗,约翰? Listen to the tape then answer this question. Which John Smith ...
- HTTP协议扫盲(六)InputStream的复用
一.问题提出 在进行网关引擎开发时,获取到一个http请求的inputstream后,可能要多次利用它进行read操作.由于流读过一次就不能再读了,所以需要实现InputStream的复制. 而Inp ...