ARC 074

感觉这场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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值