Codeforces Round #627 (Div. 3)

A 只有判段相邻的差是不是有奇数,有奇数NO,反之YES

B 因为题目说随便两个相等+另一个数就是YES,所以map存第一次出现的数字的位置,如果再次出现,只要那个数的第一个位置不是i-1就是YES反之NO

C 蛋疼题意,其实只要找两个RR之间最短的距离+1就行了

D

题意:

老师的n个想法价值ai,同学的n个想法价值bi,相互对应,找一共有多少对 ai+aj-bi-bj>0

思路:
直接将老师的思路减学生的思路,从小到大排序,用upper_bound去找他的相反数的大一点的位置,复杂度是O(lgn*n)

但是n是2e5的范围,答案可能会爆int,别忘了开ll

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define il inline
#define it register int
#define inf 0x3f3f3f3f
#define lowbit(x) (x)&(-x)
#define pii pair<int,int>
#define mak(n,m) make_pair(n,m)
#define mem(a,b) memset(a,b,sizeof(a))
#define mod 998244353
const int maxn=2e5+10;
int a[maxn],b;
int main(){
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        scanf("%d",&a[i]);
    for(int i=0;i<n;i++) {
        scanf("%d",&b);
        a[i]-=b;
    }
    sort(a,a+n);
    ll ans=0;
    for(int i=0;i<n;i++){
        int zhi=-a[i];
        int pos=upper_bound(a+i+1,a+n,zhi)-a;
        ans+=(ll)n-pos;
    }
    printf("%lld
",ans);
    return 0;
}

E

题意(题目描述进行魔改,但内容大致不变):

给n,h,l,r 四个值,表示n长度的数组,0~h-1的范围,在【l,r】区间得分能获得一个奖品(1<=n<=2000)

接下来的n个数,是按顺序的比赛得分,但是你有一个权力,每次得分可以保持不变,或者减一,然后进行累加,如果超出h,%h,问最多有多少奖品

思路:

dp【i】【j】,i表示第i个数字,j表示前面减了几次一;

cc数字i 全部累加情况(无减一)- j,这里有一个坑就是cc可能小于0,一定要while(cc<0)cc+h;而不是(cc+h)%h,因为这个h可能过小。//u1s1,比赛的时候如果写出,也会在这里被hack,因为惯性思维下意识写了(cc+h)%h

状态转移方程就是

k=(l<=cc && r>=cc);

dp[i][j]=max(dp[i-1][j-1]+k,dp[i-1][j]+k); (当j==0的时候特判一下,因为没有-1这种

最后比较max(dp【n】【i】0<=i<=n)中

#include<iostream>
#include<map>
#include<set>
#include<queue>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define ll long long
#define ull unsigned long long
#define il inline
#define it register int
#define inf 0x3f3f3f3f
#define lowbit(x) (x)&(-x)
#define pii pair<int,int>
#define mak(n,m) make_pair(n,m)
#define mem(a,b) memset(a,b,sizeof(a))
#define mod 998244353
const int maxn=2e3+10;
int n,m,t,h,l,r;
int a[maxn],dp[maxn][maxn];
int zhi[maxn][2];
int main(){
    scanf("%d%d%d%d",&n,&h,&l,&r);
    int ans=0,c=0;mem(dp,0);
    for(it i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    for(it i=1;i<=n;i++){
        c+=a[i];c%=h;
        if(l<=c && r>=c){
            dp[i][0]=dp[i-1][0]+1;
        }
        else{
            dp[i][0]=dp[i-1][0];
        }
        for(it j=1;j<=i;j++){
            int cc=(c-j+h)%h;while(cc<0){cc+=h;}
            if(l<=cc && r>=cc){
                dp[i][j]=max(dp[i-1][j-1]+1,dp[i-1][j]+1);
            }
            else{
                dp[i][j]=max(dp[i-1][j-1],dp[i-1][j]);
            }
        }
    }
    for(int i=0;i<=n;i++){
        ans=max(dp[n][i],ans);
    }
    printf("%d
",ans);
    return 0;
}

F

 题意:

树上每个点要么黑色要么白色

假设每个点为根的话,求这个点的所有子树里面最大的白点-黑点

思路:

先确定1为根结点,dfs从叶子结点往上递归,叶子结点白为1,黑为-1,其他节点看子节点累加上来大于0的加,小于0的就不加了

如果把每个点看成根,其实就是把它的父节点当成子节点,原本第一次dfs把所有子节点弄个好了,父结点因为受到这个点的影响,可能变大,可能为0或者不变,所以从1这个根结点往下遍历,求这个点的子节点对自己的影响的其他部分,在子节点加上,便是答案。

#include<iostream>
#include<map>
#include<set>
#include<queue>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define ll long long
#define ull unsigned long long
#define il inline
#define it register int
#define inf 0x3f3f3f3f
#define lowbit(x) (x)&(-x)
#define pii pair<int,int>
#define mak(n,m) make_pair(n,m)
#define mem(a,b) memset(a,b,sizeof(a))
#define mod 998244353
const int maxn=2e5+10;
vector<int>g[maxn];
int a[maxn],n,dp[maxn],ans[maxn];
void dfs1(int root,int fa){
    dp[root]=a[root];
    for(auto &i:g[root]){
        if(i==fa){continue;}
        dfs1(i,root);
        dp[root]+=max(0,dp[i]);
    }
}
void dfs2(int root,int fa,int zhi){
    ans[root]=dp[root]+zhi;
    for(auto &i:g[root]){
        if(i==fa){continue;}
        dfs2(i,root,max(ans[root]-max(dp[i],0),0));
    }
}
int main(){
    scanf("%d",&n);
    for(it i=1;i<=n;i++){
        scanf("%d",&a[i]);if(!a[i]){a[i]=-1;}
    }
    for(it i=1;i<n;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        g[u].push_back(v);
        g[v].push_back(u);
    }
    dfs1(1,0);
    dfs2(1,0,0);
    for(it i=1;i<=n;i++){
        printf(i==n?"%d
":"%d ",ans[i]);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/luoyugongxi/p/12488050.html