这些题是昨天就写了的,事情太多,博客拖到现在才写
Codeforces Round #562 (Div. 2)
A:
思路:按题意模拟一下坐车过程,可以先预处理一下a,x,b,y,将其值全部减一,然后模拟的时候在加一减一的基础上每次加一个mod,再模mod就行了,也可以不预处理a,x,b,y,这样的话就得特判处理一下到圆环边界的情况。
不预处理代码:
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
const int maxn=1e3+9;
int main(){
int i,j,k,n,a,b,x,y;
cin>>n>>a>>x>>b>>y;
i=a,j=b;
int mod=n+1,flag=0;
while(i!=x&&j!=y){
i=(i+mod+1)%mod;j=(j+mod-1)%mod;
if(i==0)i=1;
if(j==0)j=n;
if(i==j){
flag=1;
}
}
if(flag)cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
B:
思路:我们枚举第一对数中的两个数,每次枚举选一个数确定数对中的一个数,然后筛选出所有有这个数的数对,将他们剔除掉,然后我们再来将剩下数对的数计算出现次数,如果有数出现次数等于剩下的数对数,则有答案,否则没有
代码:
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
const int maxn=3e5+9;
int a[maxn][2],vis[maxn],mp[maxn];
vector<int>vec;
bool cmp(int a,int b){
return a>b;
}
int main(){
ios::sync_with_stdio(0);
cin.tie();
int i,j,k,n,m;
cin>>n>>m;
for(i=0;i<m;i++){
for(j=0;j<2;j++){
cin>>a[i][j];
}
}
int x=a[0][0],cnt=1;
for(i=1;i<m;i++){
int flag=0;
for(j=0;j<2;j++){
if(a[i][j]==x)flag=1;
}
if(flag)vis[i]=1,cnt++;
}
for(i=1;i<m;i++){
if(!vis[i]){
for(j=0;j<2;j++){
mp[a[i][j]]++;
}
}
}
for(j=0;j<=n;j++){
vec.push_back(mp[j]);
}
sort(vec.begin(),vec.end(),cmp);
if(vec[0]>=m-cnt){
cout<<"YES"<<endl;
return 0;
}
vec.clear();
memset(vis,0,sizeof(vis));
memset(mp,0,sizeof(mp));
x=a[0][1],cnt=1;
for(i=1;i<m;i++){
int flag=0;
for(j=0;j<2;j++){
if(a[i][j]==x)flag=1;
}
if(flag)vis[i]=1,cnt++;
}
for(i=1;i<m;i++){
if(!vis[i]){
for(j=0;j<2;j++){
mp[a[i][j]]++;
}
}
}
for(j=0;j<=n;j++){
vec.push_back(mp[j]);
}
sort(vec.begin(),vec.end(),cmp);
if(vec[0]>=m-cnt){
cout<<"YES"<<endl;
return 0;
}
cout<<"NO"<<endl;
}
C:
思路:
二分枚举答案,贪心check答案是否合法。假若我们枚举的答案为k的话,则我们最多的操作次数为k,对于每个数,我总是贪心进行1~k次操作(为什么允许操作少于k次,这样不是不能保证我check时一定对序列进行k此操作吗?实际上不能保证也没关系,如果我通过小于k次的操作次数x保证了序列的合法性,那么我接下来的二分一定能扫到小于等于x次的答案)让改变后的数既维持非递减性又让它比原数小。
代码:
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
const int maxn=3e5+9;
int a[maxn],n,mod;
bool check(int k){
int u=0;
// cout<<k<<endl;
for(int i=1;i<=n;i++){
int x=a[i],y=(a[i]+k)%mod;
//int z=y<x?u:x;
if(x<u&&k<u-x){
// cout<<endl;
return false;
}
else if(x<u&&k>=u-x){
continue;
}
if(x>=u&&k>=mod-x+u){
u=u;
}
else{
u=x;
}
//cout<<u<<' ';
}
//cout<<endl;
return true;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
int i,j,k;
cin>>n>>mod;
for(i=1;i<=n;i++){
cin>>a[i];
}
int l=0,r=mod;
while(l<r){
int mid=(l+r)>>1;
if(check(mid)){
r=mid;
}
else l=mid+1;
}
cout<<r<<endl;
}
D:
思路:
双指针找一下l,r,我们不妨令r总是等于x+2k的位置,每次我们找到一个l,r区间满足条件则ans+=len-r(len代表string.size,由于左指针是从0开始的,所有ans+=len-r+1是错误的),然后向右移动左指针,否则更改x值,如果r-2*k<l的话则向右移动右指针。至于为什么我们只需要额外考虑r+1,r+2,...,len-1的贡献,而不需要考虑0,1,2...l-1的贡献,这是因为我们我们的左指针是从1,2...l-1移动到l来的,如果l...r满足条件,则1...r,2...r,3...r,l-1...r必定也满足条件,所有对于一个合法的l...r,左指针作为0,1,2...l-1的贡献已经计算过了,不需要重复计算。
代码:
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const ll maxn=3e5+9;
int main(){
ll i,n;
string s;
cin>>s;
ll len=s.size();
ll j=0;
ll ans=0;;
for(i=0;i<len;i++){
ll flag=0,k=1;
while(j<len){//cout<<j<<' '<<i<<endl;
if(j-2*k<i){
j++;
k=1;
continue;
}
if(s[j]==s[j-k]&&s[j]==s[j-2*k]){
flag=1;
break;
}
k++;
}
if(flag)ans+=len-j;
else break;
}
cout<<ans<<endl;
}
POJ 1789
思路:将运输车抽象化为点,先计算出任意两点之间的距离,然后我们按边权排序,简单打一下kruskal的板子就行了
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f3f
const int maxn=2e3+9;
int mp[maxn][maxn];
string s[maxn];
struct node{
int u,v,val;
}edge[maxn*maxn];
bool cmp(node a,node b){
return a.val<b.val;
}
int f[maxn];
void init(){
for(int i=0;i<=maxn;i++)f[i]=i;
}
int find(int v){
if(f[v]==v)return v;
f[v]=find(f[v]);
return f[v];
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
int i,j,k,n;
while(cin>>n&&n){
for(i=0;i<n;i++){
cin>>s[i];
}
int cnt=0;
for(i=0;i<n;i++){
for(j=i+1;j<n;j++){
int dis=0;
for(k=0;k<7;k++){
if(s[i][k]!=s[j][k])dis++;
}
edge[cnt].val=dis;
edge[cnt].u=i;
edge[cnt++].v=j;
}
}
init();
sort(edge,edge+cnt,cmp);
int ans=0;
for(i=0;i<cnt;i++){
// cout<<edge[i].val<<' ';
int u=edge[i].u,v=edge[i].v;
int t1,t2;
t1=find(u);t2=find(v);
// cout<<t1<<' '<<t2<<endl;
if(t2!=t1){
f[t2]=t1;
// cout<<123<<endl;
ans+=edge[i].val;
}
}
cout<<"The highest possible quality is 1/";
cout<<ans<<'.'<<endl;
}
}