Educational Codeforces Round 55 (Rated for Div. 2)A,B,C,D,E总结

A:这个鬼屎题,我真的没有发现x和y的大小关系是没有确定的,导致我疯狂wa,其实这道题也就是一道水题。

代码:

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
const long long maxn=1e5+9;
int main(){
	long long i,j,k,n,t;
	cin>>t;
	while(t--){
		long long x,y,d;
		cin>>n>>x>>y>>d;
		long long tmp;
		if(y>=x){
		if((y-x)%d==0){
			cout<<(y-x)/d<<endl;
		}
		else{
			long long ans=1e9+9,flag=0;
			if(y==n){
				ans=(y-x)/d+1;
			}
			else{
				if((y-1)%d==0&&(y-1)>=d){
						flag++;
						ans=(x-1)/d+1;
						ans+=(y-1)/d;
				}
				if((n-y)%d==0&&(n-y)>=d){
						flag++;
						ans=min(ans,((n-x)/d+1+(n-y)/d));
				}
				if(flag==0){
					ans=-1;
				}
			}
			cout<<ans<<endl;
		}
		}
		else{
			if((x-y)%d==0){
			cout<<(x-y)/d<<endl;
				}
			else{
			long long ans=1e9+9,flag=0;
			if(y==1){
				ans=(x-y)/d+1;
			}
			else{
				if((n-y)%d==0&&(n-y)>=d){
						flag++;
						ans=(n-x)/d+1;
						ans+=(n-y)/d;
				}
				if((y-1)%d==0&&(y-1)>=d){
						flag++;
						ans=min(ans,((x-1)/d+1+(y-1)/d));
				}
				if(flag==0){
					ans=-1;
				}
			}
			cout<<ans<<endl;
		}
		}
	}
}

B题:这道题我们遍历一遍就行了,开两个变量分别储存相邻的连续'G’段就行了,然后通过判断连个连续'G'段中间'S'的个数来看能不能合在一起。

代码:

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
const int maxn=1e5+9;
int main(){
	int i,j,k,n;
	cin>>n;
	string s;
	cin>>s;
	int total=0,s_num=0,num1=0,num2=0,flag=0,mx=0;
	for(i=0;i<n;i++){
		if(s[i]=='G')total++;
	}
	for(i=0;i<n;i++){
		if(s[i]=='G'&&flag==0){
			num1++;
		}
		else if(s[i]=='G'&&flag==1){
			num2++;
		}
		else if(s[i]=='S'){
			//cout<<"woshigda"<<endl;
			s_num++;
			if(flag==0){flag++;
				mx=max(mx,num1);
			}
			else if(flag==1){flag++;
				mx=max(mx,num2);
			}
			if(flag==2) {
				flag=1;
				if(s_num>=3){
					mx=max(mx,max(num1,num2));
				}
				else{
					if(total-(num1+num2)>0)
					mx=max(mx,num1+num2+1);
					else{
						mx=max(mx,num1+num2);
					}
				}
				//cout<<num1<<' '<<num2<<endl;
				num1=num2;
				num2=0;
				s_num=1;
			}
		}
	}
	mx=max(mx,max(num1,num2));
	if(total-(num1+num2)>0){
		mx=max(mx,num1+num2+1);
	}
	else{
		mx=max(mx,num1+num2);
	}
	cout<<mx<<endl;
}

C题:这道题刚开始愚蠢的没有考虑完负数的情况wa了,考虑完了之后就tle,然后自己想了一下可能是因为循环了一些题目没给出的subject,于是又弄了个set容器,然后由于set的效率不是特别高,还是t了,后来看了董佬代码才发现,遍历的时候对于那些已经不满足有i个人的学科可以直接从set里面删去了,这样大大提高了运行效率

代码:

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
const int maxn=1e5+9;
#define ll long long
vector<int>a[maxn];
set<int>p;
struct node{
    int x,y;
}t[maxn];
int cnt[maxn];
bool cmp(node a,node b){
    if(a.x!=b.x)return a.x<b.x;
    return a.y>b.y;
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    int i,j,k,n,m;
    cin>>n>>m;
    int mx=0;
    for(i=0;i<n;i++){
        int x,y;
        cin>>x>>y;
        t[i].x=x;
        t[i].y=y;
        p.insert(x);
        cnt[x]++;
        if(cnt[x]>mx)mx=cnt[x];
    }
    sort(t,t+n,cmp);
    for(i=0;i<n;i++){
        if(a[t[i].x].size()==0)a[t[i].x].push_back(t[i].y);
        else{
            a[t[i].x].push_back(a[t[i].x][a[t[i].x].size()-1]+t[i].y);
        }
    }
    long long sum=0,mx_sum=0;
    vector<int>e;
    for(i=0;i<mx;i++){
        sum=0;
        for(auto it:p){
            if(a[it].size()>i&&a[it][i]>0){
                sum+=a[it][i];
            }
            if(a[it].size()==i+1)e.push_back(it);
        }
        for(auto iter:e){
            p.erase(iter);
        }
        e.clear();
        if(sum>mx_sum)mx_sum=sum;
    }
    cout<<mx_sum<<endl;
}

D题:这个题水的呀,简直就不像是D题。刚开始看他这题目我以为是个图什么的,结果仔细分析一下发现就构建一颗树就完了。

我们就先构建一条链,最后往这条链上加边就行了

代码:

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
const int maxn=1e3+9;
struct node{
    int mx_d,pos;
} a[maxn];
bool cmp(node a,node b){
    return a.mx_d>b.mx_d;
}
vector<int>edge[maxn];
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    int i,j,k,n;
    int cnt=0;
    cin>>n;
    for(i=1;i<=n;i++){
        cin>>a[i].mx_d;
        a[i].pos=i;
    }
    sort(a+1,a+n+1,cmp);
    edge[a[1].pos].push_back(a[2].pos);
    cnt++;
    for(i=3;i<=n;i++){
        if(a[i].mx_d>=2)edge[a[i-1].pos].push_back(a[i].pos),cnt++;
        else{
            if(a[i-1].mx_d>=2){
            edge[a[i-1].pos].push_back(a[i].pos);
            cnt++;}
            break;
        }
    }
    int tot_vd=cnt+1,flag=0;
    for(i=1;i<=n;i++){
        int num;
        if(i==1)num=a[i].mx_d-1;
        else num=a[i].mx_d-2;
        int t=1;
        while(t<=num){
            if(tot_vd==n)break;
            if(i==1&&!flag){cnt++;flag=1;}
            edge[a[i].pos].push_back(a[++tot_vd].pos);
            t++;
        }
    }
    if(tot_vd!=n){
        cout<<"NO"<<endl;
    }
    else{
        cout<<"YES"<<' '<<cnt<<endl;
        cout<<n-1<<endl;
        for(i=1;i<=n;i++){
            for(j=0;j<edge[i].size();j++){
                cout<<i<<' '<<edge[i][j]<<endl;
            }
        }
    }
}

E题:很有意思呀。看完大佬的博客才想明白这道题,对于这道题我们需要求的是max(cnt(c,1,n)-cnt(c.l.r)+cnt(x,l,r)),由于cnt(c,1,n)是一个固定的常量,所以其实我们只需要不断维护max(cnt(x,l,r)-cnt(c,l,r))就行了。我们可以通过DP的思想来想要怎么维护这个值,对于每一个x,找到x所有更新其x的数量的点,依次遍历。我们可以发现,如果我们把r值固定了之后,我们需要维护的值就变为了max(cnt(c,1,l-1)-cnt(x,1,l-1)),又由于对于每一个r值,由于我们是通过递推来维护的,所以对于每一个新的r值,我们其实只要考虑一种情况就行了,什么情况呢,就是r值本身就是l值的这个情况。

讲的有点乱,可能过段时间我自己来看都看不懂了。。。

代码:

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
const int maxn=5e5+9;
int a[maxn];
map<int,vector<int> >mp;
int sum[maxn];
int cnt[maxn];
int main(){
    int i,j,k,n,val;
    cin>>n>>val;
    for(i=1;i<=n;i++){
        cin>>a[i];
        sum[i]=sum[i-1]+(a[i]==val);
        mp[a[i]].push_back(i);
    }
    int mx=0,ans=sum[n];
    for(auto it:mp){
        int num=it.first;
        auto v=it.second;
        mx=0;
        for(auto iter:v){
            mx=max(mx,sum[iter-1]-cnt[num]++);
            ans=max(ans,sum[n]-(sum[iter])+mx+(cnt[num]));
        }
    }
    cout<<ans<<endl;
}

 

posted @ 2018-12-01 10:40  Zookkk  阅读(185)  评论(0编辑  收藏  举报