Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final)
考场上只做出了ABDE
C都挂了。。。
题解:
A
题解:
模拟
判断前面一段是否相同,后面一段是否相同,长度是否够(不能有重叠)
Code:
#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<iostream>
#include<queue>
#include<string>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<long long,long long> pll;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define rep(i,j,k) for(register int i=(int)(j);i<=(int)(k);i++)
#define rrep(i,j,k) for(register int i=(int)(j);i>=(int)(k);i--) ll read(){
ll x=,f=;char c=getchar();
while(c<'' || c>''){if(c=='-')f=-;c=getchar();}
while(c>='' && c<=''){x=x*+c-'';c=getchar();}
return x*f;
} int n,m;
string a,b; int main(){
n=read(),m=read();
cin>>a>>b;
int pos=-;
for(int i=;i<n;i++){
if(a[i]=='*'){
pos=i;
break;
}
}
if(pos==-){
if(a==b) puts("YES");
else puts("NO");
return ;
} if(n>m+){
puts("NO");
return ;
} for(int i=;i<pos;i++){
if(a[i]!=b[i]){
puts("NO");
return ;
}
}
for(int i=n-;i>pos;i--){
if(a[i]!=b[i-n+m]){
puts("NO");
return ;
}
}
puts("YES");
return ;
}
B
题解:
简单计算
考虑几种情况:
1. k<=n+1 那么任意一种构造都可行 答案为(k-1)/2
2. k>n+n-1 没有可行解 答案为零
3. 从(k-n)+n到(k/2+k/2) 分k的奇偶性讨论一下
Code:
#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<iostream>
#include<queue>
#include<string>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<long long,long long> pll;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define rep(i,j,k) for(register int i=(int)(j);i<=(int)(k);i++)
#define rrep(i,j,k) for(register int i=(int)(j);i>=(int)(k);i--) ll read(){
ll x=,f=;char c=getchar();
while(c<'' || c>''){if(c=='-')f=-;c=getchar();}
while(c>='' && c<=''){x=x*+c-'';c=getchar();}
return x*f;
} ll n,k; int main(){
n=read();k=read();
ll ans=;
if(k<=n+) ans=(k-)/;
else if(k>n+n-) ans=;
else{
ll nw=k/;
ll l=k-n;
if(k%==) nw--;
ans=nw-l+;
}
cout<<ans<<endl;
return ;
}
C
题解:
模拟
看到(就加进去 直到够了为止
但是如果用string s; s+='(';
由于string特别慢 于是会超时。。。
所以我们改用数组存储每一位是(还是)
Code:
#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<iostream>
#include<queue>
#include<string>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<long long,long long> pll;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define rep(i,j,k) for(register int i=(int)(j);i<=(int)(k);i++)
#define rrep(i,j,k) for(register int i=(int)(j);i>=(int)(k);i--) ll read(){
ll x=,f=;char c=getchar();
while(c<'' || c>''){if(c=='-')f=-;c=getchar();}
while(c>='' && c<=''){x=x*+c-'';c=getchar();}
return x*f;
} int n,m;
string s;
string ans;
int res[],sz; int main(){
n=read(),m=read();
cin>>s;
int num=m/;
int nw=,dif=;
for(int i=;i<s.size();i++){
if(s[i]=='('){
nw++;dif++;
res[++sz]=;
if(nw==num) break;
}
else{
if(dif){
res[++sz]=;
dif--;
}
}
}
while(dif--) res[++sz]=;
for(int i=;i<=sz;i++)
if(res[i]==) putchar('('); else putchar(')');
puts("");
return ;
}
D
题解:
首先我们把整个刷上1
然后0的情况就没有了
剩下我们按照题意模拟
每个数我们找到最左的位置和最右的位置
在线段树上更新 把这段区间刷成这个数
注意如果最大的数没有出现 那么我们得加上这个数 因为他是最后刷的 所以可以放在任何为0的位置上
然后如果现在的这个序列和原来的有矛盾(原来某一位和现在不同) 那么就是-1
否则输出这个序列
Code:
#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<iostream>
#include<queue>
#include<string>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<long long,long long> pll;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define rep(i,j,k) for(register int i=(int)(j);i<=(int)(k);i++)
#define rrep(i,j,k) for(register int i=(int)(j);i>=(int)(k);i--) ll read(){
ll x=,f=;char c=getchar();
while(c<'' || c>''){if(c=='-')f=-;c=getchar();}
while(c>='' && c<=''){x=x*+c-'';c=getchar();}
return x*f;
} const int maxn=;
int n,q;
int a[maxn];
int l[maxn],r[maxn]; struct Node{
int l,r,val;
int tag;
} tr[maxn*]; #define lc (i<<1)
#define rc (i<<1|1) void build(int i,int l,int r){
tr[i].l=l,tr[i].r=r;
if(l==r)
return;
int md=(l+r)>>;
build(lc,l,md);
build(rc,md+,r);
} void pushdown(int i){
if(!tr[i].tag) return;
tr[lc].tag=tr[rc].tag=tr[lc].val=tr[rc].val=tr[i].tag;
tr[i].tag=;
return;
} void upd(int i,int l,int r,int v){
if(tr[i].l>=l && tr[i].r<=r){
tr[i].val=v;
tr[i].tag=v;
return;
}
if(tr[i].l>r || tr[i].r<l) return;
pushdown(i);
upd(lc,l,r,v);upd(rc,l,r,v);
} int ask(int i,int pos){
if(tr[i].l>pos || tr[i].r<pos) return ;
if(tr[i].l==tr[i].r) return tr[i].val;
pushdown(i);
return max(ask(lc,pos),ask(rc,pos));
} int main(){
n=read(),q=read();
bool ok=;
int mx=;
rep(i,,n){
a[i]=read();
if(a[i]==) ok=;
mx=max(mx,a[i]);
}
if(!ok){
if(mx!=q){
puts("NO");
return ;
}
} if(mx!=q){
rep(i,,n){
if(a[i]==){
a[i]=q;
break;
}
}
} rep(i,,n){
int nw=a[i];
if(l[nw]==) l[nw]=i;
r[nw]=max(r[nw],i);
} build(,,n);
l[]=,r[]=n;
rep(i,,q)
if(l[i]) upd(,l[i],r[i],i); rep(i,,n){
int nw=ask(,i);
if(a[i] && a[i]!=nw){
puts("NO");
return ;
}
a[i]=nw;
} puts("YES");
rep(i,,n)
printf("%d ",a[i]);
puts(""); return ;
}
E
题解:
交互题
很有趣
首先我们可以方便的得出前n-1步
就是每次询问当前格子向右的一个格子能不能到(n,n)
如果能 那么向右走 否则向下走
这样我们可以走到对角线上
然后不能这么询问了
所以我们反过来做
但是因为路径不止一条 我们有可能不能走到同一个对角线上的格子
怎么办呢
我们换一种询问方式
从(n,n)开始
然后每次询问当前格子的上方一个格子能否到达之前哪条路径上与之距离为n-1的那个格子
具体见代码
如果能走 就往上走 否则往左走
为什么是对的呢
因为我们一定会得到所有路径里最靠右的那一条路径
Code:
#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<iostream>
#include<queue>
#include<string>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<long long,long long> pll;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define rep(i,j,k) for(register int i=(int)(j);i<=(int)(k);i++)
#define rrep(i,j,k) for(register int i=(int)(j);i>=(int)(k);i--) ll read(){
ll x=,f=;char c=getchar();
while(c<'' || c>''){if(c=='-')f=-;c=getchar();}
while(c>='' && c<=''){x=x*+c-'';c=getchar();}
return x*f;
} int n;
string ans1,ans2; bool ask(int a,int b,int c,int d){
printf("? %d %d %d %d\n",a,b,c,d);
fflush(stdout);
string ret;
cin>>ret;
if(ret=="YES") return ;
else return ;
} int main(){
n=read();
int nwx=,nwy=;
for(int i=;i<n;i++){
bool nw=ask(nwx,nwy+,n,n);
if(nw) ans1=ans1+'R',nwy++;
else ans1=ans1+'D',nwx++;
}
int xx=n,yy=n;
for(int i=n-;i>=;i--){
if(ans1[i]=='R') nwy--;
else nwx--;
bool nw=ask(nwx,nwy,xx-,yy);
if(nw) ans2='D'+ans2,xx--;
else ans2='R'+ans2,yy--;
}
cout<<"! "<<ans1<<ans2<<endl;
fflush(stdout);
return ;
}
F
题解:
好题
首先我们先把那些“我的路径”加进图中
用并查集维护连通性
然后对于每一条新的路径:
如果两端在一个联通块内 那么记录下来
否则加进图中 并且更新并查集
这样我们得到一棵树和一些边
然后dfs一遍整理树的结构 求出每个点的father和depth
下面是精华部分
我们还是用一个并查集维护这棵树
现在我们要做的操作是:对于之前每条未加进图中的边,我们把两端点之间的路径更新成这条边的边权,不能重复更新
因为输入的时候就是排好序的所以不需要重复更新
问题在于每条边如何正好被更新一次
就是说我们在更新后边的时候要跳过一些前边被更新过的边
我们用fa[x]表示这个点在往上跳的时候跳到的点 也就是说从x到fa[x]的路径都被更新过 并且fa[x]到f[fa[x]]这条边没有被更新
那么直接这样跳一跳直到两个端点跳到同一个点就结束了
怎么维护fa呢
我们只需要在往上跳的时候令fa[x]=fp(f[x])就可以了 fp在这里表示的就是找到上一个没有更新的点
Code:
#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<iostream>
#include<queue>
#include<string>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<long long,long long> pll;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define rep(i,j,k) for(register int i=(int)(j);i<=(int)(k);i++)
#define rrep(i,j,k) for(register int i=(int)(j);i>=(int)(k);i--) ll read(){
ll x=,f=;char c=getchar();
while(c<'' || c>''){if(c=='-')f=-;c=getchar();}
while(c>='' && c<=''){x=x*+c-'';c=getchar();}
return x*f;
} const int maxn=; int n,m,k,num;
int fa[maxn]; struct Edge{
int fr,to,len,tp;
};
vector<Edge> edges;
vector<int> gr[maxn]; inline int fp(int x){if(fa[x]==x) return x;return fa[x]=fp(fa[x]);}
inline void uni(int a,int b){a=fp(a),b=fp(b);if(a!=b) fa[a]=b;} void add_edge(int a,int b,int l,int t){
edges.pb((Edge){a,b,l,t});
edges.pb((Edge){b,a,l,t});
num=edges.size();
gr[a].pb(num-);
gr[b].pb(num-);
} int A[maxn],B[maxn],L[maxn],cnt;
int f[maxn],d[maxn],res[maxn]; void dfs(int x,int pa=){
f[x]=pa;
for(int i=;i<gr[x].size();i++){
int ind=gr[x][i];
Edge nw=edges[ind];
if(nw.to==f[x]) continue;
d[nw.to]=d[x]+;
dfs(nw.to,x);
}
} int ans[maxn]; int main(){
// freopen("in","r",stdin);
n=read(),k=read(),m=read();
rep(i,,n) fa[i]=i;
for(int i=;i<=k;i++){
int a=read(),b=read();
add_edge(a,b,,);
uni(a,b);
}
for(int i=;i<=m;i++){
int x=read(),y=read(),l=read();
int fx=fp(x),fy=fp(y);
if(fx!=fy){fa[fx]=fy;add_edge(x,y,l,);}
else{A[++cnt]=x,B[cnt]=y,L[cnt]=l;}
} d[]=;
dfs(); for(int i=;i<=n;i++)
fa[i]=i; for(int i=;i<=cnt;i++){
int nwx=A[i],nwy=B[i],nwl=L[i];
nwx=fp(nwx),nwy=fp(nwy);
while(nwx!=nwy){
if(d[nwx]>=d[nwy]){
res[nwx]=nwl;
fa[nwx]=fp(f[nwx]);
nwx=fa[nwx];
}
else{
res[nwy]=nwl;
fa[nwy]=fp(f[nwy]);
nwy=fa[nwy];
}
}
} //for(int i=1;i<=n;i++) cout<<res[i]<<endl; ll ans=;
for(int i=;i<=n;i++){
for(int j=;j<gr[i].size();j++){
int ind=gr[i][j];
Edge nw=edges[ind];
if(nw.to==f[i] && nw.tp==){
if(fa[i]==i){
puts("-1");
return ;
}
ans+=res[i];
}
}
}
cout<<ans<<endl;
return ;
}
总结
1. 字符串string类很慢 尽量不要用string加string的操作
2. 想好了再写 不要出现细节错误
Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final)的更多相关文章
- E - Down or Right Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final)
http://codeforces.com/contest/1023/problem/E 交互题 #include <cstdio> #include <cstdlib> #i ...
- Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final)-D- Array Restoration
我们知道不满足的肯定是两边大中间小的,这样就用RMQ查询两个相同等值的区间内部最小值即可,注意边界条件 #include<bits/stdc++.h> #define x first #d ...
- Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final)-C-Bracket Subsequence
#include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> ...
- Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final)-A-Single Wildcard Pattern Matching
#include<iostream> #include<algorithm> #include<stdio.h> #include<string.h> ...
- Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final) E. Down or Right
从(1,1,n,n)每次只变一个坐标,进行询问. 如果问到对角线有距离限制, 再从(1,1,n/2,n/2)询问到(n/2,n/2,n,n) 记住前半部分贪心忘上走,后本部分贪心往右走 因为最后的路线 ...
- D. Recovering BST Codeforces Round #505 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final)
http://codeforces.com/contest/1025/problem/D 树 dp 优化 f[x][y][0]=f[x][z][1] & f[z+1][y][0] ( gcd( ...
- Codeforces Round #505 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final) -B C(GCD,最长连续交替序列)
B. Weakened Common Divisor time limit per test 1.5 seconds memory limit per test 256 megabytes input ...
- Codeforces Round #505 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final) B. Weakened Common Divis
题目链接 让你找一个数,使得这个数,可以被每个二元组的两个数中的一个数整除. 先将第一个二元组的两个数质因数分解一下,分解的质数加入set中,然后,对剩下的n-1个二元组进行遍历,每次遍历到的二元组对 ...
- Codeforces Round #505 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final)
A : A. Doggo Recoloring time limit per test 1 second memory limit per test 256 megabytes input stand ...
随机推荐
- 给大二学生——能够再坚持一年的ACM
[来信] 我是大二学生,就读于一所非常普通的大学.学校ACM基本零起步,去年才開始搞,我大一大二花了非常多时间搞acm,如今不太想放弃.但学校基本没人愿意搞这个. 非常快就要大三了,我一直在纠结要不要 ...
- 下载Google官方/CM Android源码自己主动又一次開始的Shell脚本
国内因为某种原因,下载CM或Google官方的Android源码总easy中断.总看着机器.一中断就又一次运行repo sync还太麻烦,所以我特意编写了一段shell脚本(download.sh). ...
- u-boot简单学习笔记(三)——AR9331 uboot启动分析
1.最开始系统上电后 ENTRY(_start)程序入口点是 _start 由board/ap121/u-boot.lds引导 2._start: cpu/mips/start.S 是第一个源程序文 ...
- Python调用C/Fortran混合的动态链接库--上篇
内容描述: 在32位或64位的windows或GNU/Linux系统下利用Python的ctypes和numpy模块调用C/Fortran混合编程的有限元数值计算程序 操作系统及编译环境: 32bit ...
- 【酷Q&C++】如何利用酷Q制作一个机器人?
——酷Q Air教程 要想阅读本篇教程,读者需要基本的C++知识以及Visual Studio 2010/2015/2017 首先,需要从官方网站下载软件 https://cqp.cc/t/23253 ...
- https证书/即SSL数字证书申请途径和流程
国际CA机构GlobalSign中国 数字证书颁发中心网站:http://cn.globalsign.com https证书即SSL数字证书,是广泛用 于网站通讯加密传输的解决方案,是提供通信保 ...
- UIButton常见属性和方法
一.创建,两种方法: 1. 常规的 initWithFrame UIButton *btn1 = [[UIButton alloc]initWithFrame:CGRectMake(10, 10, 8 ...
- HihoCoder1084: 扩展KMP(二分+hash,求T串中S串的数量,可以失配一定次数)
时间限制:4000ms 单点时限:4000ms 内存限制:256MB 描述 你知道KMP吗?它是用于判断一个字符串是否是另一个字符串的子串的算法.今天我们想去扩展它. 在信息理论中,在两个相同长度的字 ...
- javascript之存储数据-cookie,localStorage,sessionStorage
cookie: 存储一些简单的数据,以文本形式放到本地,大小4kb 存储:document.cookie='name=value' 取值:document.cookie(字符串) 期限:expires ...
- win7Setx修改环境变量
SETX.exe (Resource Kit, Windows 7) Set environment variables permanently, SETX can be used to set En ...