感觉这场ARC的题目挺适合中国选手…所以好像很多人AK..
D
用堆预处理出1~i,i~3N保留N个数的最小和最大和
枚举剩下的2N个数的第N个数
E
f[r][g][b]表示r,g,b为三种颜色最后出现的位置,i=max(r,g,b),1~i以内的限制都满足,1~i的填色数
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
#define __ %=Mod
using namespace std;
const ll Mod = 1e9+7;
const int maxn = 305;
int n,m;
struct node{int l,r,x;}a[maxn];
inline bool cmp(const node x,const node y){return x.r<y.r;}
ll f[maxn][maxn][maxn];
void trans(const int i,const int x,const int y,const int z)
{
ll &tmp=f[x][y][z];
(f[i][y][z]+=tmp)__;
(f[x][i][z]+=tmp)__;
(f[x][y][i]+=tmp)__;
tmp=0;
}
int cal(const int x,const int y,const int z,const int l)
{
int re=0;
if(x>=l) re++;
if(y>=l) re++;
if(z>=l) re++;
return re;
}
void judge(const int x,const int y,const int z,int l,int r)
{
bool flag=true;
for(int i=l;i<=r;i++)
{
if(a[i].x!=cal(x,y,z,a[i].l)){ flag=false; break; }
}
if(!flag) f[x][y][z]=0;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++) scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].x);
sort(a+1,a+m+1,cmp);
f[0][0][0]=1ll; int pos=1;
for(int i=1;i<=n;i++)
{
for(int j=i-1;j>=0;j--) for(int k=i-1;k>=0;k--)
{
if(f[i-1][j][k]) trans(i,i-1,j,k);
if(f[j][i-1][k]) trans(i,j,i-1,k);
if(f[j][k][i-1]) trans(i,j,k,i-1);
}
int np=pos; while(np<=m&&a[np].r==i) np++; np--;
if(pos>np) continue;
for(int j=i-1;j>=0;j--) for(int k=i-1;k>=0;k--)
{
if(f[i][j][k]) judge(i,j,k,pos,np);
if(f[j][i][k]) judge(j,i,k,pos,np);
if(f[j][k][i]) judge(j,k,i,pos,np);
}
pos=np+1;
}
ll re=0;
for(int j=n-1;j>=0;j--) for(int k=n-1;k>=0;k--)
{
if(f[n][j][k]) (re+=f[n][j][k])__;
if(f[j][n][k]) (re+=f[j][n][k])__;
if(f[j][k][n]) (re+=f[j][k][n])__;
}
printf("%lld\n",re);
return 0;
}
F
对于(i,j)的荷叶,i和j之间连流量为1的双向边,st和sx,sy连流量无限的双向边,ed同理,跑最小割
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
#define inf 1e9
using namespace std;
const int maxn = 110;
const int maxp = 1100;
const int maxm = 110000;
int n,m;
struct edge{int y,c,nex;}a[maxm]; int len,fir[maxp],fi[maxp];
inline void ins(const int x,const int y,const int c){a[++len]=(edge){y,c,fir[x]};fir[x]=len;}
int st,ed;
int h[maxp];
queue<int>q;
bool bfs()
{
for(int i=1;i<=ed;i++) h[i]=0;
h[st]=1; q.push(st);
while(!q.empty())
{
const int x=q.front(); q.pop();
for(int k=fir[x],y=a[k].y;k;k=a[k].nex,y=a[k].y)
if(!h[y]&&a[k].c) h[y]=h[x]+1,q.push(y);
}
return h[ed]>0;
}
int dfs(const int x,const int flow)
{
if(x==ed) return flow;
int delta=0;
for(int &k=fi[x],y=a[k].y;k&&delta<flow;k=a[k].nex,y=a[k].y) if(h[y]==h[x]+1&&a[k].c)
{
int mk=dfs(y,min(a[k].c,flow-delta));
delta+=mk;
a[k].c-=mk; a[k^1].c+=mk;
}
if(!delta) h[x]=0;
return delta;
}
int Flow()
{
int re=0;
while(bfs())
{
for(int i=1;i<=ed;i++) fi[i]=fir[i];
re+=dfs(st,inf);
}
return re;
}
int rec[maxn][maxn],sx,sy,ex,ey;
char str[maxn];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%s",str);
for(int j=0;j<m;j++)
{
if(str[j]=='o') rec[i][j+1]=1;
else if(str[j]=='S') sx=i,sy=j+1;
else if(str[j]=='T') ex=i,ey=j+1;
}
}
if(sx==ex||sy==ey) return puts("-1"),0;
len=1;
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(rec[i][j])
{
ins(i,n+j,1); ins(n+j,i,1);
}
st=n+m+1,ed=st+1;
ins(st,sx,inf); ins(st,n+sy,inf);
ins(ex,ed,inf); ins(n+ey,ed,inf);
printf("%d\n",Flow());
return 0;
}