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;
}