Educational Codeforces Round 87 (Rated for Div. 2)(D,E补题)

A,B,C1比较简单没什么说的,C2........图都画不出来,就是再考画图.......画出图不就是一个三角函数

D

两种做法
(1)树状数组

#include<iostream>
using namespace std;

int n;
int a[1000005],c[1000005]; //对应原数组和树状数组

int lowbit(int x){
    return x&(-x);
}

void updata(int i,int k){    //在i位置加上k
    while(i <= n){
        c[i] += k;
        i += lowbit(i);
    }
}

int getsum(int i){        //求A[1 - i]的和
    int res = 0;
    while(i > 0){
        res += c[i];
        i -= lowbit(i);
    }
    return res;
}

int search(int l,int r,int num)
{
    int left = 1,right = r;
    int mid;
while(left < right)
{
  //这里不需要加1。我们考虑如下的情况,最后只剩下A[i],A[i + 1]。
  //首先mid = i,如果A[mid] > key,那么right = left = i,跳出循环,如果A[mid] < key,left = right = i + 1跳出循环,所有不会死循环。
  mid = (left + right) / 2;
  if(getsum(mid) >= num)//如果要求大于等于可以加上等于,也可以是check(A[mid])
    right = mid;
  //因为找的是大于key的第一个元素,那么比A[mid]大的元素肯定不是第一个大于key的元素,因为A[mid]已经大于key了,所以把mid+1到后面的排除
  else
    left = mid + 1;
  //如果A[mid]小于key的话,那么A[mid]以及比A[mid]小的数都需要排除,因为他们都小于key。不可能是第一个大于等于key的元素,
}
return right;
}



int main()
{
    int q;
    scanf("%d%d",&n,&q);
    for(int i = 1; i <= n; i++)
    scanf("%d",&a[i]);
    for(int i = 1; i <= n ;i++)
    {
        updata(a[i],1);
    }
    int flag = 0;
    for(int i = 1; i <= q; i++)
    {
        int k;
        scanf("%d",&k);
        if(k > 0)
        {
            updata(k,1);
            flag++;
        }
        else{
            k = -k;
            flag -- ;
            int pos = search(1,n,k);
            if(pos > 0)
            updata(pos,-1);
        }
    }
    if(n + flag <= 0)
    printf("0\n");
    else{
        int pos = search(1,n,1);
        if(pos >= 1)
        printf("%d\n",pos);
    }
}

(2)二进制枚举答案
用二分直接对于每种情况,用数组判断大小,然后缩小区间,最后剩下的,就是答案

#include<bits/stdc++.h>
using namespace std;
int a[1000009];
int k[1000009];
int n,q;
int check(int x)
{
    int ans=0;
    for(int i=0; i<n; i++)
    {
        if(a[i]<=x)
            ans++;
    }
    for(int i=0; i<q; i++)
    {
        if(k[i]>0&&k[i]<=x)
            ans++;
        if(k[i]<0&&abs(k[i])<=ans)
            ans--;
    }
    return ans;
}
signed main()
{

    scanf("%d%d",&n,&q);
    for(int i=0; i<n; i++)
        scanf("%d",&a[i]);
    for(int i=0; i<q; i++)
         scanf("%d",&k[i]);
    if(check(1e9)==0)
    {
        cout<<0;
        return 0;
    }
    int l=0,r=1e6+1;
    while(r>l)
    {
        int mid=r+l;
        mid/=2;
        if(check(mid)>0)
            r=mid;
        else
            l=mid;
    }
    cout<<r;
}

E

题意:给定一个图,n个点,m条边,然后对于每个点赋值,可以赋值为1,2,3,并且每个边的两点的差的绝对值为1,然后输出每个点的值,答案不唯一
题解:因为每个边的两点的差的绝对值为1,所以相当于赋值奇偶数
然后我们可以把图当成1棵树,根节点为奇数,第二层第四层....为偶数,第三层第五层为奇数,如果搜到某个点,发现它可以与之前某个已经搜过的点相连,那么如果这两个点奇偶性相同,那么整张图直接no
然后这样之后我们发现还要满足n1+n2+n3=n所以对于每张图不一定是以根节点为奇数开始的,然后进行一个dp,来确定每个图的起始点的奇偶性,如果奇偶数的点的关系与n1,n2,n3的不等,输出no,还有上面的都要有标记,最后再进行回溯来确定每个点

#include <bits/stdc++.h>

#define F first
#define S second
#define pb push_back
#define pii pair <int,int>

using namespace std;

const int N=5e3+9,M=1e5+9;
vector <int> adj[N];
int comp[N],num[N][2],cnt=0;
int par[N][N];
int a,b,c,ans[N];
bool mrk[N],dp[N][N],col[N],res[N];

void DFS1(int u,int x,int cl){
    mrk[u]=1;
    comp[u]=x;
    col[u]=cl;
    num[x][cl]++;
    for(int v:adj[u]){
        if(!mrk[v]) DFS1(v,x,!cl);
        else if(col[v]==col[u]){
            cout<<"NO",exit(0);
        }
    }
}

void DFS2(int u,int x){
    mrk[u]=1;
    if(col[u]==x) ans[u]=2,b--;
    else{
        if(a>0) ans[u]=1,a--;
        else ans[u]=3,c--;
    }
    for(int v:adj[u]) if(!mrk[v]) DFS2(v,x);
}

int32_t main(){
    ios::sync_with_stdio(0);cin.tie(0);
    int n,m;
    cin>>n>>m;
    cin>>a>>b>>c;
    for(int i=0;i<m;i++){
        int u,v;
        cin>>u>>v;
        adj[u].pb(v); adj[v].pb(u);
    }
    for(int i=1;i<=n;i++) if(!mrk[i]) DFS1(i,++cnt,0);
    dp[0][0]=1;
    for(int i=1;i<=cnt;i++){
        for(int j=0;j<=b;j++){
            if(j-num[i][0]>=0 && dp[i-1][j-num[i][0]]){
                dp[i][j]=1;
                par[i][j]=0;
            }
            if(j-num[i][1]>=0 && dp[i-1][j-num[i][1]]){
                dp[i][j]=1;
                par[i][j]=1;
            }
        }
    }
    if(!dp[cnt][b]) return cout<<"NO",0;
    for(int i=cnt;i>0;i--){
        res[i]=par[i][b];
        b-=num[i][par[i][b]];
    }
    fill(mrk,mrk+N,0);
    for(int i=1;i<=n;i++) if(!mrk[i]) DFS2(i,res[comp[i]]);
    cout<<"YES"<<endl;
    for(int i=1;i<=n;i++) cout<<ans[i];
    return 0;
}
全部评论

相关推荐

11-15 18:39
已编辑
西安交通大学 Java
全村最靓的仔仔:卧槽,佬啥bg呢,本也是西交么
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务