Codeforces Round #620 (Div. 2) 题解
A. Two Rabbits
思路:
很明显,如果(y-x)%(a+b)==0的话ans=(y-x)/(a+b),否则就为-1
#include<iostream> #include<algorithm> using namespace std; const int maxn = 100000+5; int main(){ int k; scanf("%d",&k); while(k--){ long long x,y,a,b,ans; cin>>x>>y>>a>>b; if((y-x)%(a+b)) ans=-1; else ans=(y-x)/(a+b); cout<<ans<<endl; } }
B. Longest Palindrome
思路:
直接暴力找对于每个串的反串(也就是对于每个i都有a[i]==a[n-i-1]),然后接着再前面没有被找到过的串中找一个自身也是回文串的串放在答案串的中间即可
写的稍稍有一些麻烦
#include<iostream> #include<algorithm> #include<vector> #include<cstring> #define inf 0x3f3f3f3f using namespace std; typedef long long ll; const int maxn=105; string s[maxn]; int flag[maxn]; string ans="",temp=""; int main() { int n,m,cnt=0,x,y; cin>>n>>m; for(int i=1;i<=n;i++) cin>>s[i],flag[i]=0; for(int i=1;i<=n;i++){ if(flag[i]) continue; for(int j=i+1;j<=n;j++){ y=0; for(int k=0;k<m;k++){ if(s[i][k]!=s[j][m-k-1]){ y=1; break; } } if(!y){ ans+=s[i]; flag[j]=1; flag[i]=1; cnt+=2; break; } } if(!y) continue; } for(int i=1;i<=n;i++){ if(flag[i]) continue; int x=0; for(int j=0;j<m/2;j++){ if(s[i][j]!=s[i][m-j-1]){ x=1; break; } } if(!x){ temp+=s[i]; cnt++; flag[i]=1; break; } } if(cnt==0){ cout<<"0"<<endl<<endl; return 0; } cout<<cnt*m<<endl; cout<<ans<<temp; for(int i=ans.size()-1;i>=0;i--) cout<<ans[i]; return 0; }
C. Air Conditioner
思路:
先对顾客到店的时间进行排序,之后对于每一个顾客判断[Li , Ri] 与 [LI - t ,Ri + t] 是否有交集即可
#include <bits/stdc++.h> #define maxn 1000010 using namespace std; #define ll long long struct node{ ll t,l,h; }costomer[110]; int main() { int t; scanf("%d",&t); while(t--){ int n; ll m; scanf("%d%lld",&n,&m); ll mi=m,ma=m,tmp=0; int kk=0; for (int i = 0; i <n ; ++i) { cin>>costomer[i].t>>costomer[i].l>>costomer[i].h; mi-=(costomer[i].t-tmp); ma+=(costomer[i].t-tmp); if(ma<costomer[i].l||mi>costomer[i].h){kk=1;} else { mi=max(mi,costomer[i].l); ma=min(ma,costomer[i].h); tmp=costomer[i].t; } } if(kk)cout<<"NO"<<endl; else cout<<"YES"<<endl; } return 0; }
D. Shortest and Longest LIS
思路:
直接贪心即可,最短序列的话,对于一串大于号,我们把当前未使用过的数尽可能的放在左边
最长序列就是反过来,尽可能的放未使用过的小的数即可
#include<iostream> #include<algorithm> #include<cstring> using namespace std; const int maxn=2e5+10; int ans[maxn]; int main() { int t,n; cin>>t; string s; while(t--){ cin>>n>>s; int num=n,las=0; for(int i=0;i<n;i++){ if(s[i]=='>'||i==n-1){ for(int j=i;j>=las;j--) ans[j]=num--; las=i+1; } } for(int i=0;i<n;i++) printf("%d ",ans[i]); cout<<endl; num=1,las=0; for(int i=0;i<n;i++){ if(s[i]=='<'||i==n-1){ for(int j=i;j>=las;j--) ans[j]=num++; las=i+1; } } for(int i=0;i<n;i++) printf("%d ",ans[i]); cout<<endl; } return 0; }
E. 1-Trees and Queries
思路:
只要找到,a到b的最短路径跟k的关系就好了
这个关系就是:只要最短路径长度小于K,并且奇偶性跟K相同即可
证明的话很简单:如果走到终点还没到路径长度还没到k的话,就可以不停的往回走一次,再走向终点,这样路程的长度就为dis+2i,要想最后能回到终点很明显x要与k同奇偶
最短只需要通过求两点的LCA就可以求出,当然新加进来的一条边会对路径产生影响
但是我们只要再判断dis(a,x)+dis(b,y)+1 与 dis(a,y)+dis(b,x)+1 即可
#include<iostream> #include<cstring> #include<algorithm> #include<cmath> #define maxn 100005 using namespace std; struct edge{ int next,v; }edges[maxn*2]; int head[maxn],cnt,dep[maxn],f[maxn][21],n,q; void init() { memset(head,-1,sizeof(head)); cnt=0; } void addedge(int u,int v) { edges[cnt].next=head[u]; edges[cnt].v=v; head[u]=cnt++; } void dfs(int u,int fa) { dep[u]=dep[fa]+1; for(int i=0;i<=19;i++) f[u][i+1]=f[f[u][i]][i]; for(int i=head[u];i!=-1;i=edges[i].next) { int v=edges[i].v; if(v==fa) continue; f[v][0]=u; dfs(v,u); } } int lca(int x,int y) { if(dep[x]<dep[y]) swap(x,y); for(int i=20;i>=0;i--) { if(dep[f[x][i]]>=dep[y]) x=f[x][i]; if(x==y) return x; } for(int i=20;i>=0;i--) { if(f[x][i]!=f[y][i]) { x=f[x][i]; y=f[y][i]; } } return f[x][0]; } int getdis(int a,int b){return dep[a]+dep[b]-2*dep[lca(a,b)];} int main() { scanf("%d",&n); init(); int u,v,q,a,b,x,y,k; for(int i=1;i<n;i++){ scanf("%d%d",&u,&v); addedge(u,v),addedge(v,u); } dfs(1,0); scanf("%d",&q); while(q--){ int flag=0; scanf("%d%d%d%d%d",&x,&y,&a,&b,&k); int len1=getdis(a,b),len2=getdis(a,x)+getdis(b,y)+1,len3=getdis(a,y)+getdis(b,x)+1; if(len1<=k&&(k-len1)%2==0) flag=1; if(len2<=k&&(k-len2)%2==0) flag=1; if(len3<=k&&(k-len2)%2==0) flag=1; if(flag) cout<<"YES"<<endl; else cout<<"NO"<<endl; } }