2018牛客网 多校1

J    Different Integers

将原数组复制加到尾部,1-l,r-n的区间就变成r-n+l了

然后线段树处理不同数字个数

#include<iostream>
#include<algorithm>
#include<cstring>
#include<stdio.h>
#include<map>
using namespace std;
const int N=2e5+10;
int n,m;
int cnt[N<<2];
struct qu
{
    int l,r,i;
}q[N];
bool cmp(qu a,qu b)
{
    if(a.r!=b.r)return a.r<b.r;
    else return a.l<b.l;
}
void update(int x,int k,int num,int l,int r)
{
    if(l==r&&l)
    {
        cnt[x]=num;
        return;
    }
    int mid=(l+r)/2;
    if(k<=mid)update(x*2,k,num,l,mid);
    else update(x*2+1,k,num,mid+1,r);
    cnt[x]=cnt[x*2]+cnt[x*2+1];
}
int query(int x,int l,int r,int L,int R)
{
    if(l<=L&&r>=R)
    {
        return cnt[x];
    }
    int mid=(L+R)/2;
    int s=0;
    if(l<=mid)s+=query(x*2,l,r,L,mid);
    if(r>mid)s+=query(x*2+1,l,r,mid+1,R);
    return s;
}
int a[N],b[N];
int ans[N];
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        memset(cnt,0,sizeof(cnt));
        memset(ans,0,sizeof(ans));
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            b[i]=a[i];
        }
        for(int i=n+1;i<=2*n;i++)
        {
            b[i]=a[i-n];
        }
        int z=2*n;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&q[i].l,&q[i].r);
            if(q[i].l>q[i].r)
            {
                q[i].l=1;
                q[i].r=n;
                q[i].i=i;
                continue;
            }
            int k=q[i].l+n;
            q[i].l=q[i].r;
            q[i].r=k;
            q[i].i=i;
        }
        sort(q+1,q+m+1,cmp);
        map<int,int>mp;
        mp.clear();
        for(int i=1,j=1;i<=2*n;i++)
        {
            if(mp[b[i]])
            {
                update(1,mp[b[i]],0,1,z);
                update(1,i,1,1,z);
                mp[b[i]]=i;
 
            }
            else
            {
 
                update(1,i,1,1,z);
                mp[b[i]]=i;
            }
            while(j<=m&&q[j].r==i)
            {
                ans[q[j].i]=query(1,q[j].l,q[j].r,1,z);
                j++;
            }
        }
       for(int i=1;i<=m;i++)
        {
            printf("%d\n",ans[i]);
        }
    }
    return 0;
}

D   Two Graphs

给你一个大图,再给一个小图,问大图里有多少个小图,只要用到的路径不同即算不同

暴力枚举  假设小图中k个点,从大图中选k个点再k!枚举。

因为可能重复,所以需要计算一下小图本身重复的可能性

再用之前算的答案除一下

#include<bits/stdc++.h>
using namespace std;
const int N=1e3;
int b[9][9];
int s[9][9];
map<int,int>by;
map<int,int>sy;
int pa[9];
int pa1[9];
int vis[9];
int viss[9];
int ans=0;
int cnt,cnt2;
int f=0;
int anss=0;
int paa[9];
void dfs1(int js)
{
    if(js>cnt)
    {
        int f1=1;
        int f2=1;
         for(int i=1;i<=cnt;i++)
         {
             for(int j=i+1;j<=cnt;j++)
             {
                  if(s[i][j]!=b[pa1[i]][pa1[j]]&&s[i][j]==1)
                    f1=0;
             }
         }
         if(f1==1)
            ans++;
         return ;
    }
    for(int i=0;i<cnt;i++)
    {
        if(!vis[i])
        {
            vis[i]=1;
            pa1[js]=pa[i];
            dfs1(js+1);
            vis[i]=0;
        }
    }
}
void dfs(int x,int js)
{
    if(x>cnt2&&js<=cnt-1)
        return ;
    if(js>=cnt)
    {
        memset(vis,0,sizeof(vis));
        dfs1(1);
        return ;
    }
    pa[js]=x;
    dfs(x+1,js+1);
    dfs(x+1,js);
}
void dfss(int x)
{
    if(x>cnt)
    {
        int f=1;
        for(int i=1;i<=cnt;i++)
        {
            for(int j=1;j<=cnt;j++)
                if(s[i][j]!=s[paa[i]][paa[j]])
                    f=0;
        }
        if(f)
            anss++;
        return ;
    }
    for(int i=1;i<=cnt;i++)
    {
        if(viss[i]==0)
        {
            paa[x]=i;
            viss[i]=1;
            dfss(x+1);
            viss[i]=0;
        }
    }
}
int main()
{
    int n,x1,x2;
    while(~scanf("%d%d%d",&n,&x1,&x2))
    {
        by.clear();
        sy.clear();
        memset(b,0,sizeof(b));
        memset(s,0,sizeof(s));
        cnt=0;
        cnt2=0;
        int u,v;
        for(int i=0;i<x1;i++)
        {
             cin>>u>>v;
             if(sy[u]==0)sy[u]=++cnt;
             if(sy[v]==0)sy[v]=++cnt;
             s[sy[u]][sy[v]]=1;
             s[sy[v]][sy[u]]=1;
        }
        for(int i=0;i<x2;i++)
        {
             cin>>u>>v;
             if(by[u]==0)by[u]=++cnt2;
             if(by[v]==0)by[v]=++cnt2;
             b[by[u]][by[v]]=1;
             b[by[v]][by[u]]=1;
        }
        ans=0;
        anss=0;
        memset(viss,0,sizeof(viss));
        dfss(1);
        dfs(1,0);
        cout<<ans/anss<<endl;
    }
    return 0;
}

E Removal(dp)

https://tokitsukaze.live/2018/07/22/2018niuke1.E/

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e5+10;
const int mod=1e9+7;
ll dp[N][15];
int Next[N][15];
int a[N];
int main()
{
    int n,m,k;
    while(~scanf("%d%d%d",&n,&m,&k))
    {
        memset(Next,0,sizeof(Next));
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        for(int i=1;i<=k;i++)
        {
            Next[n][i]=n+1;
        }
        for(int i=n;i>=1;i--)
        {
            for(int j=1;j<=k;j++)
            {
                Next[i-1][j]=Next[i][j];
            }
            Next[i-1][a[i]]=i;
        }
        dp[0][0]=1;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<=m;j++)
            {
                for(int t=1;t<=k;t++)
                {
                    int to=Next[i][t];
                    int z=to-i-1;
                    if(z+j<=m)
                    {
                        (dp[to][z+j]+=dp[i][j])%=mod;
                    }
 
                }
            }
        }
        ll ans=0;
        for(int i=0;i<=m;i++)
        {
            ans=(ans+dp[n-i][m-i])%mod;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

A    Monotonic Matrix

答案是Cn+m,n2 -Cn+m,m-1Cn+m,n-1

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll dp[2050][2050];
const int ll mod=1e9+7;
void init()
{
    dp[0][1]=dp[1][1]=1;
    for(int i=2;i<=2002;i++)
    {
        dp[0][i]=dp[i][i]=1;
        for(int j=1;j<i;j++)
        {
            dp[j][i]=(dp[j][i-1]+dp[j-1][i-1])%mod;
        }
    }
}
int main()
{
    init();
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        ll ans=(dp[n][m+n]*dp[n][m+n]%mod+mod-dp[n-1][n+m]*dp[m-1][n+m]%mod)%mod;
        printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/threeh20/article/details/81172703