考场上只做出了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)的更多相关文章

  1. 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 ...

  2. 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 ...

  3. 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> ...

  4. 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> ...

  5. 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) 记住前半部分贪心忘上走,后本部分贪心往右走 因为最后的路线 ...

  6. 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( ...

  7. 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 ...

  8. Codeforces Round #505 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final) B. Weakened Common Divis

    题目链接 让你找一个数,使得这个数,可以被每个二元组的两个数中的一个数整除. 先将第一个二元组的两个数质因数分解一下,分解的质数加入set中,然后,对剩下的n-1个二元组进行遍历,每次遍历到的二元组对 ...

  9. 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 ...

随机推荐

  1. 手把手编写自己的PHPMVC框架

    1 什么是MVC MVC模式(Model-View-Controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(Controller ...

  2. Python 002- 爬虫爬取淘宝上耳机的信息

    参照:https://mp.weixin.qq.com/s/gwzym3Za-qQAiEnVP2eYjQ 一般看源码就可以解决问题啦 #-*- coding:utf-8 -*- import re i ...

  3. Android app身体质量指数(BMI)

    针对中国人的标准身高体重来測算,提示您身体的健康状况. 提示您是否应该锻炼.节食或者补充营养等.第一时间知道您的健康状况. 下载地址:http://android.myapp.com/myapp/de ...

  4. Web 监听器

    什么事web 监听器? Servlet规范中定义的一种特殊类 用于监听ServletContext.HttpSession和ServletRequest等象的创建与销毁的事件 用监听域对象的属性发生修 ...

  5. Aspose 直接插入SQL Server DataTalbe

    原文链接:http://www.cnblogs.com/hellohongfu/p/7362830.html 下面的代码可以根据excel文件,生成创建表的SQL,以及测试InsertSQL .方法将 ...

  6. Random 类生成随机数

    Random类 (java.util) Random类中实现的随机算法是伪随机,也就是有规则的随机.在进行随机时,随机算法的起源数字称为种子数(seed),在种子数的基础上进行一定的变换,从而产生需要 ...

  7. (C)*p++和*++p区别

    接下来,通过示例彻底理解自增运算符的两种用法(自减的用法与之类似,只不过是加1变成了减1). 1.++i和i++的区别 如清单1(注意代码中的注释): #include <stdio.h> ...

  8. 基于Python 的简单推荐系统

    def loadExData(): return[[1,1,1,0,0], [2,2,2,0,0], [1,1,1,0,0], [5,5,5,0,0], [1,1,0,2,2], [0,0,0,3,3 ...

  9. Centos6.8防火墙设置

    # 查看防火墙状态 service iptables status   # 停止防火墙 service iptables stop   # 启动防火墙 service iptables start   ...

  10. 一步一步学Silverlight 2系列(8):使用样式封装控件观感

    述 Silverlight 2 Beta 1版本发布了,无论从Runtime还是Tools都给我们带来了很多的惊喜,如支持框架语言Visual Basic, Visual C#, IronRuby, ...