前言:
发现这套题目挺简单的……于是来水一篇博客。
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("");
}
}
}