ICPC小米网络赛第二场

A

对于第一个2,统计即可。

对于第一个0,统计的同时还要看会不会超过第一个2的数量,因为超过了,我们也没有前面的2与之进行匹配。

对于第二个2,统计的同时还要看会不会超过第一个0的数量,同时,我们还要注意,我们不能超过第一个2的数量的一半,因为我们要使得匹配数尽量大,总共2的数量尽量要对半分。

对于第二个0,同理。

#include <bits/stdc++.h>
#define debug freopen("r.txt","r",stdin)
#define mp make_pair
#define ri register int
#define pb push_back
using namespace std;
typedef long long ll;
typedef double lf;
typedef pair<ll, ll> pii;
const int maxn = 1e6+10;
const ll INF = 1e18;
const int mod = 1e9+7;
const double eps=1e-6;
const double PI=acos(-1.0);
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;}
ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
int n,i,l2,l0,r2,r0;
char s[maxn];
int main()
{
    while (~scanf("%d",&n))
    {
        scanf("%s",s+1);
        l2=l0=r2=r0=0;
        for (i=1;i<=n;i++)
        {
            int x=(s[i]-'0');
            l2+=(x==2);
            l0+=(x==0 && l0<l2);
            r2+=(x==2 && r2<(l2>>1) && r2<l0);
            r0+=(x==0 && r0<(l0>>1) && r0<r2);
        }
        cout<<r0<<endl;
    }
    return 0;
}
View Code

D

水题?我并不这么认为……,也可能是我线代知识掌握的不牢固的原因。

G

对于每次操作,可以近似看为,一个环,把它从某个位置断开,然后展开的操作。顺序、逆序,一共2n遍,同时判重使用hash。

#include <bits/stdc++.h>
#define debug freopen("r.txt","r",stdin)
#define mp make_pair
#define ri register int
#define pb push_back
using namespace std;
typedef long long ll;
typedef long long ull;
typedef double lf;
typedef pair<ll, ll> pii;
const int maxn = 1e6+10;
const ll INF = 1e18;
const int mod = 1e9+7;
const int hash_num = 131;
const double eps=1e-6;
const double PI=acos(-1.0);
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;}
ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
map<ull,int>mapp;
ull hash1[maxn], base[maxn];
int n,i,a[maxn],num;
ull get_hash(int l,int r)
{
    return hash1[r]-hash1[l-1]*base[r-l+1];
}
void _hash()
{
    for (int i=1;i<=2*n;i++)
        hash1[i]=hash1[i-1]*hash_num+(a[i]);
}
void init()
{
    base[0]=1;
    for (int i=1;i<=maxn;i++) 
        base[i]=base[i-1]*hash_num;
}
int main()
{
    init();
    while (~scanf("%d",&n))
    {
        mapp.clear();
        for (i=1;i<=n;i++) a[i]=read(),a[i+n]=a[i];
        _hash();
        ull sum=0;
        num=0;
        for (i=1;i<=n;i++)
        {
            sum=get_hash(i,i+n-1);
            if (!mapp[sum]) num++;
            mapp[sum]=1;
        }
        reverse(a+1,a+1+2*n);
        _hash();
        for (i=1;i<=n;i++) 
        {
            sum=get_hash(i,i+n-1);
            if (!mapp[sum]) num++;
            mapp[sum]=1;
        }
        cout<<num<<endl;
    }
    return 0;
}
View Code

H

这题的正解我不会……,正解是需要分治的那种,而不是以性价比排序的那种,虽然两种都能过,但是第二种会被hack。分治那种用到了一个我听都没听过的算法,而我也没学会……

I

首先很容易想到的和最长公共子序列有关,应该算是拓展题。

假设串a匹配到第 i 个位置,串b匹配到第 j 个位置,对于串a的下一位字母 i+1,如果它字典序小于串b的下一位字母 j+1,那么我们可以把串b后面的字母都能加进来,统计一次答案了。

而第二种统计答案的方法是,找到两者的最长公共子序列,再把串b后面的字母加进来,统计答案。

#include <bits/stdc++.h>
#define debug freopen("r.txt","r",stdin)
#define mp make_pair
#define ri register int
#define pb push_back
using namespace std;
typedef long long ll;
typedef double lf;
typedef pair<ll, ll> pii;
const int maxn = 2e3+10;
const ll INF = 1e18;
const int mod = 1e9+7;
const double eps=1e-6;
const double PI=acos(-1.0);
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;}
ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
char s1[maxn],s2[maxn];
int len1,len2,ans,i,j,dp[maxn][maxn];
int main()
{
    while (~scanf("%s%s",s1+1,s2+1))
    {
        len1=strlen(s1+1);
        len2=strlen(s2+1);
        for (i=0;i<=len1;i++)
            for (j=0;j<=len2;j++) dp[i][j]=0;
        ans=0;
        for (i=0;i<=len1;i++)
            for (j=0;j<=len2;j++)
            {
                if (i && j)
                {            
                    dp[i][j]=max(dp[i][j-1],dp[i-1][j]);
                    if (s1[i]==s2[j])    
                        dp[i][j]=dp[i-1][j-1]+1;
                    else if (s1[i]<s2[j])
                    {
                        ans=max(ans,dp[i-1][j-1]*2+len1-i+1+len2-j+1);
                    }
                }
                ans=max(ans,dp[i][j]*2+(len2-j));
            }
        cout<<ans<<endl;    
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/Y-Knightqin/p/13942175.html