TJOI2014day1 bzoj 5154~5156

前言:

发现这套题目挺简单的……于是来水一篇博客。

5154: [Tjoi2014]匹配:

这题暴力的一匹……直接先跑一次费用流得出答案,然后再看一下删除原来的匹配边之后能不能再跑出原来的答案即可。

代码:

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pa pair<int,int>
const int Maxn=85;
const int inf=1061109567;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return x*f;
}
int n,h[Maxn][Maxn],id[Maxn][Maxn];
struct Edge{int x,y,d,c,next;}e[Maxn*Maxn<<2];
int last[Maxn<<1],len=1;
void ins(int x,int y,int d,int c)
{
    int t=++len;
    e[t].x=x;e[t].y=y;e[t].d=d;e[t].c=c;
    e[t].next=last[x];last[x]=t;
}
void addedge(int x,int y,int d,int c){ins(x,y,d,c),ins(y,x,0,-c);}
int f[Maxn<<1],pre[Maxn<<1];
bool in[Maxn<<1];
int st,ed;
bool spfa()
{
    pre[st]=-1;
    memset(f,63,sizeof(f));f[st]=0;
    memset(in,false,sizeof(in));
    queue<int>q;q.push(st);
    while(!q.empty())
    {
        int x=q.front();q.pop();in[x]=false;
        for(int i=last[x];i;i=e[i].next)
        {
            int y=e[i].y;
            if(e[i].d&&f[x]+e[i].c<f[y])
            {
                pre[y]=i;
                f[y]=f[x]+e[i].c;
                if(!in[y])q.push(y),in[y]=true;
            }
        }
    }
    return(f[ed]!=inf);
}
int to[Maxn];
int ans=0;
void work()
{
    int t=ed,mn=inf;
    while(pre[t]!=-1)
    {
        mn=min(mn,e[pre[t]].d);
        ans-=e[pre[t]].c;
        t=e[pre[t]].x;
    }
    t=ed;
    while(pre[t]!=-1)
    {
        e[pre[t]].d-=mn;e[pre[t]^1].d+=mn;
        t=e[pre[t]].x;
    }
}
int main()
{
    n=read();
    st=(n<<1)+1,ed=(n<<1)+2;
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
    {
        h[i][j]=read();
        addedge(i,j+n,1,-h[i][j]);
        id[i][j]=len-1;
    }
    for(int i=1;i<=n;i++)addedge(st,i,1,0),addedge(i+n,ed,1,0);
    while(spfa())work();
    printf("%d\n",ans);
    int tmp=ans;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        if(!e[id[i][j]].d){to[i]=j;break;}  
    }
    for(int i=1;i<=n;i++)
    {
        memset(last,0,sizeof(last));len=1;
        for(int j=1;j<=n;j++)
        for(int k=1;k<=n;k++)
        if(j!=i||k!=to[i])addedge(j,k+n,1,-h[j][k]);
        for(int j=1;j<=n;j++)addedge(st,j,1,0),addedge(j+n,ed,1,0);
        ans=0;
        while(spfa())work();
        if(tmp!=ans)printf("%d %d\n",i,to[i]);
    }
}

5155: [Tjoi2014]电源插排:

动态开点线段树即可。

代码:

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pa pair<int,int>
const int Maxq=100010;
const int inf=2147483647;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return x*f;
}
map<int,int>mp;
int lc[Maxq*33],rc[Maxq*33],pos[Maxq*33],ll[Maxq*33],rr[Maxq*33],len[Maxq*33],c[Maxq*33];
int n,q,tot=0,root=0;
int get(int l,int r)
{
    return (l+r)/2+((r-l)&1);
}
void up(int x,int l,int r)
{
    int mid=l+r>>1;
    int lcl=ll[lc[x]],lcr=rr[lc[x]],lclen=len[lc[x]],lcp=pos[lc[x]];
    int rcl=ll[rc[x]],rcr=rr[rc[x]],rclen=len[rc[x]],rcp=pos[rc[x]];
    if(!lc[x])lcl=lcr=lclen=mid-l+1,lcp=get(l,mid);
    if(!rc[x])rcl=rcr=rclen=r-mid,rcp=get(mid+1,r);
    c[x]=c[lc[x]]+c[rc[x]];
    len[x]=max(lcr+rcl,max(lclen,rclen));
    if(len[x]==rclen)pos[x]=rcp;
    else if(len[x]==lcr+rcl)pos[x]=get(mid-lcr+1,mid+rcl);
    else pos[x]=lcp;
    if(lcl==mid-l+1)ll[x]=lcl+rcl;
    else ll[x]=lcl;
    if(rcr==r-mid)rr[x]=rcr+lcr;
    else rr[x]=rcr;
}
void modify(int &x,int l,int r,int p,int v)
{
    if(!x)x=++tot;
    if(l==r)
    {
        if(v)pos[x]=-1;
        else pos[x]=l;
        ll[x]=rr[x]=len[x]=1-v,c[x]=v;
        return;
    }
    int mid=l+r>>1;
    if(p<=mid)modify(lc[x],l,mid,p,v);
    else modify(rc[x],mid+1,r,p,v);
    up(x,l,r);
}
int query(int x,int l,int r,int fl,int fr)
{
    if(!x)return 0;
    if(l==fl&&r==fr)return c[x];
    int mid=l+r>>1;
    if(fr<=mid)return query(lc[x],l,mid,fl,fr);
    else if(fl>mid)return query(rc[x],mid+1,r,fl,fr);
    else return query(lc[x],l,mid,fl,mid)+query(rc[x],mid+1,r,mid+1,fr);
}
int main()
{
    n=read(),q=read();
    bool fir=true;
    while(q--)
    {
        int x=read();
        if(!x)
        {
            int l=read(),r=read();
            printf("%d\n",query(root,1,n,l,r));
        }
        else
        {
            if(!mp[x])
            {
                int p;
                if(fir)p=get(1,n),fir=false;
                else p=pos[root];
                modify(root,1,n,p,1);
                mp[x]=p;
            }
            else
            {
                modify(root,1,n,mp[x],0);
                mp[x]=0;
            }
        }
    }
}

5156: [Tjoi2014]拼图:

爆搜即可。

代码:

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pa pair<int,int>
const int inf=2147483647;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return x*f;
}
int n,b[5][5],ans;
struct P{int r,c,id,area,v[5][5];}a[20];
bool cmp(P a,P b){return a.area>b.area;}
char s[6];
bool check(int x,int y,int o)
{
    for(int i=1;i<=a[o].r;i++)
    for(int j=1;j<=a[o].c;j++)
    if(a[o].v[i][j])
    {
        if(b[x+i-1][y+j-1])return false;
    }
    return true;
}
void work(int x,int y,int o,int op)
{
    for(int i=1;i<=a[o].r;i++)
    for(int j=1;j<=a[o].c;j++)
    if(a[o].v[i][j])
    {
        if(op==1)b[x+i-1][y+j-1]=a[o].id;
        else b[x+i-1][y+j-1]=0;
    }
}
int Ans[5][5];
void dfs(int x)
{
    if(ans==2)return;
    if(x==n+1)
    {
        ans++;
        if(ans>1)return;
        for(int i=1;i<=4;i++)
        for(int j=1;j<=4;j++)
        Ans[i][j]=b[i][j];
        return;
    }
    for(int i=1;i<=4-a[x].r+1;i++)
    for(int j=1;j<=4-a[x].c+1;j++)
    if(check(i,j,x))
    {
        work(i,j,x,1);
        dfs(x+1);
        work(i,j,x,-1);
    }
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        int S=0;
        memset(b,0,sizeof(b));
        for(int i=1;i<=n;i++)
        {
            a[i].r=read(),a[i].c=read();a[i].id=i;a[i].area=0;
            for(int j=1;j<=a[i].r;j++)
            {
                scanf("%s",s+1);
                for(int k=1;k<=a[i].c;k++)
                a[i].v[j][k]=s[k]-'0',a[i].area+=s[k]-'0';
            }
            S+=a[i].area;
        }
        if(S!=16){puts("No solution");continue;}
        sort(a+1,a+1+n,cmp);
        ans=0;
        dfs(1);
        if(!ans){puts("No solution");continue;}
        if(ans==2){puts("Yes, many!");continue;}
        puts("Yes, only one!");
        for(int i=1;i<=4;i++)
        {
            for(int j=1;j<=4;j++)
            printf("%d",Ans[i][j]);
            puts("");
        }
    }
}

猜你喜欢

转载自blog.csdn.net/baidu_36797646/article/details/80041960