AtCoder Regular Contest 104——C區間dp

Fighting_Peter發表於2020-10-06

A - Plus Minus

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<iostream>
#include<algorithm>
int main()
{
    IO;
    int T=1;
    //cin>>T;
    while(T--)
    {   
       int x,y;
       cin>>x>>y;
       cout<<(x+y)/2<<' '<<(x-y)/2<<'\n';
    }
    return 0;
    
}

B - DNA Sequence

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const ll mod=998244353;
const int N=5010;
int cnt[4][N];
string s;
int n;
int main()
{
    IO;
    int T=1;
    //cin>>T;
    
    while(T--)
    {   
        cin>>n;
        cin>>s;
        s="."+s;
        for(int i=1;i<=n;i++)
        {
            if(s[i]=='A') cnt[0][i]++;
            else if(s[i]=='T') cnt[1][i]++;
            else if(s[i]=='G') cnt[2][i]++;
            else cnt[3][i]++;
        }
        for(int i=1;i<=n;i++)
            for(int j=0;j<4;j++) cnt[j][i]+=cnt[j][i-1];
        int res=0;
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)
            {
                int A=cnt[0][j]-cnt[0][i-1];
                int T=cnt[1][j]-cnt[1][i-1];
                int G=cnt[2][j]-cnt[2][i-1];
                int C=cnt[3][j]-cnt[3][i-1];
                if(A==T&&G==C) res++;
                
            }
        cout<<res<<'\n';
        
    }
    return 0;
    
}

就會個AB,C看了一下午才明白,真的菜

C - Fair Elevator

Heltion大佬題解
讀個題都都不明白,讀了半天+看題解才慢慢理解題目意思
注意:just one person got on or off at each floor:每層樓只有一個人上電梯或者下電梯(我說為什麼有 n n n個人 2 n 2n 2n樓層,原來是這意思),這樣就不難得出非法的序列情況即記錯的情況(Additionally, the remaining records may be incorrect)

如果出現重複的A,B或者A>B則顯然不合法.

重複的A,B就不滿足每層樓只有一個人上電梯,A>B顯然不可能在上升的電梯中高層上底層下hh。

電梯中有多少人那麼他們的 C i ( B i − A i − 1 ) C_i(B_i-A_i-1) Ci(BiAi1)就必須相等。

某個長度為2L的區間能單獨作為一段存在當且僅當:
1.左半區間不出現B,右半區間不出現A;
2.如果其中的A,B是成對給出的,則它們必須相差L;
3.如果其中的A,B相差L,則它們必須是成對給出的.

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const ll mod=998244353;
const int N=210;
int a[N],b[N];
int n;
int p[N],w[N];
int f[N][N];
int main()
{
    IO;
    bool ok=1;
    memset(p,-1,sizeof p);
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i]>>b[i];
        if(a[i]!=-1) 
        {
            if(p[a[i]]!=-1) ok=0;
            else p[a[i]]=1;
        }
        if(b[i]!=-1)
        {
            if(p[b[i]]!=-1) ok=0;
            else p[b[i]]=0;
        }
        if(a[i]!=-1&&b[i]!=-1)
        {
            if(a[i]>b[i]) ok=0;
            else w[a[i]]=w[b[i]]=b[i]-a[i];
        }
    }
    if(!ok) return cout<<"No\n",0;
    for(int l=1;l<=n;l++)
        for(int i=1;i+2*l-1<=2*n;i+=2)
        {
            int j=i+2*l-1;
            //[i,i+l-1] [i+l,j]  i上 i+l下
            // 必須相差l
            f[i][j]=1;
            for(int k=i;k<i+l;k++)
            {
                // 下直接非法
                if(p[k]==0) f[i][j]=0;
                // w[k]!=0說明成對出現AB那麼相差必須是l
                if(w[k]&&w[k]!=l) f[i][j]=0;
                // 相差l必須成對出現即w[k]存在 同一個人
                if(!w[k]&&p[k]==1&&p[k+l]==0) f[i][j]=0;
            }
            for(int k=i+l;k<=j;k++)
            {
                if(p[k]==1) f[i][j]=0;
                if(w[k]&&w[k]!=l) f[i][j]=0;
            }
            for(int k=i+1;k<j;k+=2)
                if(f[i][k]&&f[k+1][j])  
                    f[i][j]=1;
        }    
    cout<<(f[1][2*n]?"Yes\n":"No\n");
    return 0;
    
}

看題每次都露細節導致題目讀不懂
要加油哦~

相關文章