考场上只做出了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. HDU2489 Minimal Ratio Tree 【DFS】+【最小生成树Prim】

    Minimal Ratio Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  2. angularjs中常见错误

    使用angularjs时间不是非常长,理解不够透彻.但为刚開始学习的人还是能够帮助点的. 1.回调函数. . ...-->切记它是异步的,出现莫名其妙的问题记得查看一下 2.内存泄露. .... ...

  3. glib的安装(2)

    一: glib库的路径:    http://ftp.acc.umu.se/pub/GNOME/sources/glib/2.20/ 二: 下载glib库: wget  http://ftp.acc. ...

  4. PHP琐碎学习

    在子类中如果定义了__construct则不会调用父类的__construct,如果需要同时调用父类的构造函数,需要使用parent::__construct()显式的调用. class Car { ...

  5. 回溯法——求解N皇后问题

    问题描写叙述 八皇后问题是十九世纪著名数学家高斯于1850年提出的.问题是:在8*8的棋盘上摆放8个皇后.使其不能互相攻击,即随意的两个皇后不能处在允许行.同一列,或允许斜线上. 能够把八皇后问题拓展 ...

  6. C# XML序列化与反序列化与XML格式详解

    1.https://www.cnblogs.com/sandyliu1999/p/4844664.html XML是有层次结构的,序列化实际就是内存化,用连续的结构化的内存来存储表示一个对象,那么这两 ...

  7. dedecms文章内页获取缩略图的调用标签

    点评:文章内容页缩略图的调用,图片集内容页缩略图的调用很容易混淆,内页想调用缩略图用[filed:picname/]来实现是错误的 文章内容页缩略图的调用,图片集内容页缩略图的调用,相信大家都想找这个 ...

  8. Perl解析JSON数据精解

    简介:JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.它基于JavaScript(Standard ECMA-262 3rd Edition - Dece ...

  9. ssl原理及应用

    今天学习网络通信,看到使用ssl(Secure Sockets Layer)进行加密,由于对ssl只是有些概念上的了解,对于具体应用原理.过程和如何使用不慎了解,于是学习了一番,总结如下: 1. 为什 ...

  10. Objective-C基础知识

    内联函数 “内联函数”是一个很老的概念,在其他语言譬如C++语言中也出现了.所谓“内联函数”指的是“有函数的结构,但不具备函数的性质,类似于宏替换功能的代码块”. 在实际应用中,常常把规模较小.逻辑较 ...