Codeforces Round #592 (Div. 2)

B. Rooms and Staircases

从前往后,或者从后往前枚举下该位置一二层各走一次

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define sc(x) scanf("%I64d",&x);
#define pb push_back
#define fi first
#define se second
#define P pair<int,int>
#define si signed
char s[1005];
int n;
si main()
{
    int t;
    sc(t);
    while(t--){
        sc(n);
        scanf("%s",s+1);
        int ans=0;
        int p=0,t=0;
        for(int i=1;i<=n;i++){
            if(s[i]=='1'){
                t+=1;
            }
        }
        if(t==n){
            cout<<2*t<<'\n';
        }else{
            ans=2*t+n-t;
            if(t==0){cout<<n<<'\n';continue;}
            int ed= 0;
            for(int i=n;i>=1;i--){
                if(s[i]=='1'){
                    ed= i;
                    break;
                }
            }
            p=0;
            for(int i=1;i<=ed;i++){
                if(s[i]=='1'){
 
                    ans=max(ans,p+2*(ed-i+1));
                    p+=2;
                }
                else {ans=max(ans,p+2*(ed-i+1));p++;}
            }
            ed =1;
            for(int i=1;i<=n;i++){
                if(s[i]=='1'){
                    ed= i;
                    break;
                }
            }
            p=0;
            for(int i=n;i>=ed;i--){
                if(s[i]=='1'){
 
                    ans=max(ans,p+2*(i-ed+1));
                    p+=2;
                }
                else {ans=max(ans,p+2*(i-ed+1));p++;}
            }
            cout<<ans<<'\n';
        }
    }
}

C. The Football Season

给定 n,p,w,d;w<d

要求

x⋅w+y⋅d=p

x+y+z =n

x⋅w+y⋅d=p

x+y< =n

被扩展欧几里得坑了==

数据范围爆long long

先求下__gcd(w,d) ,如果p%__gcd(w,d)!=0,直接判无解

容易发现x越大,x+y就会越大

然后x从p/w+1往0开始枚举,不超过d的范围一定能找到合适的解

如果没找到,说明不能满足x+y<=n,输出-1

#include<bits/stdc++.h>
using namespace std;
#define int long long
signed main()
{
   int  n,p,d,w;
   scanf("%I64d%I64d%I64d%I64d",&n,&p,&w,&d);
   int a =__gcd(w,d);
   if(p%a!=0||p/w>n){
    cout<<"-1"<<endl;return 0;
   }
   for(int i = p/w+1,j=0;i>=0&&j<10*d;j ++,i--){
    if((p-i*w)%d==0){
        int x= (p-i*w)/d;
        if(x+i<=n&&x>=0){
            cout<<i<<' '<<x<<' '<<n-i-x<<endl;
            return 0;
        }
    }
   }
   cout<<-1<<'\n';
 
}

D. Paint the Tree

一棵树要求任意一条三长路上的三个点颜色不同

所以只能是一条链

记录下祖父,父节点颜色,dfs跑几遍就行

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define sc(x) scanf("%I64d",&x);
#define pb push_back
#define fi first
#define se second
#define P pair<int,int>
#define si signed
vector<int>G[100005];
int C[100005][3];
int A[100005];
int B[100005];
int n;
void dfs(int x,int fa,int pa)
{
 
    for(int i=0; i<3; i++)
    {
        if(i!=A[fa]&&i!=A[pa])
        {
            A[x]=i;
            break;
        }
 
    }
    for(int i=0; i<G[x].size(); i++)
    {
        if(G[x][i]!=fa)
        {
            dfs(G[x][i],x,fa);
        }
    }
 
 
}
si main()
{
    sc(n);
    for(int i=0; i<3; i++)
    {
        for(int j=1; j<=n; j++)
        {
            sc(C[j][i])
        }
    }
    int a,b;
    for(int i=1; i<n; i++)
    {
        sc(a) sc(b);
        G[a].pb(b);
        G[b].pb(a);
        if(G[a].size()>2||G[b].size()>2)
        {
            puts("-1");
            return 0;
        }
    }
    A[0]=-1;
    /*cout<<dfs(1,0,0)<<endl;
    for(int i=1;i<=n;i++){
        cout<<B[i]+1<<' ';
    }*/
    for(int i=1; i<=n; i++)
    {
        if(G[i].size()==1)
        {
 
            int a=i,b=G[a][0],c=((G[b][0]==a)?G[b][1]:G[b][0]);
            int ans=1e18;
            for(int i=0; i<3; i++)
            {
                for(int j=0; j<3; j++)
                {
                    int t=0;
                    if(i!=j)
                    {
                        A[a]=i;
                        A[b]=j;
                        dfs(c,b,a);
                        for(int i=1; i<=n; i++)
                        {
                            t+=C[i][A[i]];
                        }
                        if(ans>t)
                        {
                            ans=t;
                            for(int i=1; i<=n; i++)B[i]=A[i];
                        }
                    }
 
                }
            }
            cout<<ans<<'\n';
            for(int i=1; i<=n; i++)
            {
                cout<<B[i]+1<<' ';
            }
            return 0;
 
        }
    }
}

E. Minimizing Difference

这题似曾相识

给一个数组,k次操作,每次操作可以选择一个数加一或者减一

求不超过k次操作后,该数组最大值最小值之差最小为多少

思路:

sort 维护一下前缀和

二分答案

check:

从左至右

滑动窗口,对每一个数字Ai,枚举它是下界,Ai+x是上界时的代价,取min

然后从右至左

判断一下最小代价是否大于k

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define sc(x) scanf("%I64d",&x);
#define si signed
int n,k;
int A[100005];
int B[100005];
bool check(int x)
{
    int t=1e18;
    int y=n,z=1;
    int i=n,cnt=0;
   // cout<<x<<"xxxxxxxxxxx"<<endl;
    while(y>=1)
    {
        if(i==0)i=1;
        for(i; i>=1; i--)
        {
            if(A[y]-A[i]>x)
            {
 
                t =min(t,(A[y]-x)*i-B[i]+cnt);
                //cout<<t<<" "<<i<<endl;
                break;
            }
        }
         cnt=(B[n]-B[y-1]-A[y-1]*(n-y+1));
         y--;
    }
 
    cnt=0;
    i=1;
 
    while(z<=n)
    {
        if(i>n)i=n;
        for(i; i<=n; i++)
        {
            if(A[i]-A[z]>x)
            {
                t =min(t,B[n]-B[i-1]-(A[z]+x)*(n-i+1)+cnt);
 
                break;
            }
        }
         cnt=A[z+1]*z-(B[z]);
        z++;
    }
    //cout<<t<<endl;
 
    return t<=k;
}
si main()
{
    sc(n);
    sc(k);
    for(int i=1; i<=n; i++)
    {
        sc(A[i])
    }
    sort(A+1,A+1+n);
    int l = 0,r=A[n]-A[1];
    for(int i=1; i<=n; i++){B[i]=A[i]+B[i-1];}
    while(l+1<=r)
    {
        int mid =(l+r)/2;
        if(check(mid))
        {
            r=mid;
        }
        else
        {
            l=mid+1;
        }
    }
    cout<<l<<endl;
    /*int ans = A[n]-A[1];
    for(int i=0; i<=n; i++)
    {
        if(k<((A[i]*i)-B[i]))
        {
            break;
        }//min
        k-=(A[i]*i)-B[i];
        int l=i,r=n;
        while(l+1<=r)
        {
            int mid=(l+r)/2;
            if(B[n]-B[mid]-(n-mid)*A[mid]<=k)
            {
                r = mid;
            }
            else
            {
                l = mid+1;
            }
        }
        int x= A[l-1],y=A[l];
          if(l-1<i){
            x=A[l];
        }
        while(x+1<=y)
        {
            int mid =(x+y)/2;
            if(B[n]-B[l-1]-(n-l+1)*mid<=k)
            {
                y=mid;
            }
            else
            {
                x=mid+1;
            }
        }
        int cnt=A[i];
        if(k-B[n]+B[l-1]+(n-l+1)*x>l-1&&l-1>0){
            cnt+=min(k/(l-1),x-A[i]);
        }
        ans=min(x-cnt,ans);
    }
    cout<<ans<<'\n';*/
}

 

posted @ 2019-11-02 11:12  liulex  阅读(151)  评论(0编辑  收藏  举报