BZOJ3173~3175 TJOI2013 DAY2

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Elemmir/article/details/51141316

BZOJ3173 最长上升子序列

数从小到大加入,所以以每个数结尾的最大长度等于位置在它前面的数的长度的最大值+1,求每个数的位置的方法同POJ2828.

http://blog.csdn.net/elemmir/article/details/50131127

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
using namespace std;
const int maxn = 100005;
const int INF  = 0x3f3f3f3f;
struct node{
    int L,R;
    int s;
}tree[maxn<<2];
bool fg=0;
int n,a[maxn],b[maxn],c[maxn],p[maxn];
void pushup(int p){
    if(fg==0)
        tree[p].s=tree[p<<1].s+tree[p<<1|1].s;
    else 
        tree[p].s=max(tree[p<<1].s,tree[p<<1|1].s);
}
void build(int p,int L,int R){
    tree[p].L=L;tree[p].R=R;
    if(L==R){tree[p].s=a[L];return;}
    int mid=(L+R)>>1;
    build(p<<1,L,mid);build(p<<1|1,mid+1,R);
    pushup(p);
}
void modify(int p,int pos,int d){
    int L=tree[p].L,R=tree[p].R;
    if(L==R){
        tree[p].s+=d;return;
    }
    int mid=(L+R)>>1;
    if(pos<=mid)modify(p<<1,pos,d);
    else modify(p<<1|1,pos,d);
    pushup(p);
}
int query(int p,int k){
    int L=tree[p].L,R=tree[p].R;
    if(L==R)return L;
    int siz=tree[p<<1].s;
    if(k<=siz)return query(p<<1,k);
    else return query(p<<1|1,k-siz);
}
int mx(int p,int L,int R){
    int n_L=tree[p].L,n_R=tree[p].R;
    if(L<=n_L && n_R<=R)return tree[p].s;
    int mid=(n_L+n_R)>>1;
    int ret=-INF;
    if(L<=mid)ret=max(ret,mx(p<<1,L,R));
    if(mid<R)ret=max(ret,mx(p<<1|1,L,R));
    return ret;
}
int main(){
    freopen("sequence.in","r",stdin);
    freopen("sequence.out","w",stdout);

    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&b[i]);
    fg=0;
    for(int i=1;i<=n;i++)a[i]=1;
    build(1,1,n);
    for(int i=n;i>=1;i--){
        p[i]=query(1,b[i]+1);
        modify(1,p[i],-1);
    }
    fg=1;
    for(int i=1;i<=n;i++)a[i]=0;
    build(1,1,n);
    for(int i=1;i<=n;i++){
        int pos=p[i];
        int tmp=mx(1,1,p[i]);
        modify(1,p[i],tmp+1);
        int ans=tree[1].s;
        printf("%d\n",ans);
    }
}

BZOJ3174 拯救小矮人

贪心+DP

http://blog.csdn.net/vmurder/article/details/42879403

BZOJ3175 攻击装置

二分图最大独立集,同网络流24题T24

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
using namespace std;
const int maxn = 205;
const int INF  = 0x3f3f3f3f;
int g[maxn][maxn];
int n,m,S=0,T=0;
const int mx[]={1,2,2,1,-1,-2,-2,-1};
const int my[]={-2,-1,1,2,2,1,-1,-2};
#define read(x) {\
    x=0;char ch=getchar();\
    for(;ch<'0' || ch>'9';ch=getchar());\
    for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';\
}
struct edge{
    int x,y,next,v;
    edge(){}
    edge(int _x,int _y,int _nt,int _v)
    :x(_x),y(_y),next(_nt),v(_v){}
}e[maxn*maxn*16];
int head[maxn*maxn],cur[maxn*maxn],tot=1,h[maxn*maxn];
inline void addedge(int x,int y,int v){
    e[++tot]=edge(x,y,head[x],v);head[x]=tot;
    e[++tot]=edge(y,x,head[y],0);head[y]=tot;
}
int q[maxn*maxn],l,r;
inline bool BFS(){
    memset(h,-1,sizeof(h));
    h[S]=0;
    q[l=r=0]=S;
    while(l<=r){
        int x=q[l++];
        if(x==T)return 1;
        for(int v,y,i=head[x];i;i=e[i].next){
            y=e[i].y,v=e[i].v;
            if(v && h[y]==-1){
                h[y]=h[x]+1;
                if(y==T)return 1;
                q[++r]=y;
            }
        }
    }
    return 0;
}
inline int DFS(int x,int f){
    if(x==T)return f;
    int used=0,tmp;
    for(int v,y,i=cur[x];i;i=e[i].next){
        y=e[i].y;v=e[i].v;
        if(v && h[y]==h[x]+1){
            tmp=DFS(y,min(v,f-used));
            e[i].v-=tmp;e[i^1].v+=tmp;
            used+=tmp;
            if(e[i].v)cur[x]=i;
            if(f==used)return f;
        }
    }
    if(!used)h[x]=-1;
    return used;
}
int maxf(){
    int ret=0;
    while(BFS()){
        for(int i=S;i<=T;i++)cur[i]=head[i];
        ret+=DFS(S,INF);        
    }
    return ret;
}
int main(){
    freopen("attack.in","r",stdin);
    freopen("attack.out","w",stdout);

    read(n)
    memset(g,0,sizeof(g));m=0;
    char str[maxn];
    for(int i=1;i<=n;i++){
        gets(str+1);
        for(int j=1;j<=n;j++)
            if(str[j]=='1'){g[i][j]=-1;m++;}
    }

    for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)
        if(g[i][j] == 0)g[i][j]=++T;
    S=0;T=n*n+1;
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++){
        if(g[i][j]==-1)continue;
        if((i+j) % 2 == 0){
            addedge(S,g[i][j],1);
            for(int k=0;k<8;k++){
                int x=i+mx[k],y=j+my[k];
                if(x<1 || x>n || y<1 || y>n)continue;
                if(g[x][y]==-1)continue;
                addedge(g[i][j],g[x][y],INF);
            }
        }else{
            addedge(g[i][j],T,1);
        }
    }
    printf("%d\n",n*n-m-maxf());
}
阅读更多
换一批

没有更多推荐了,返回首页