BZOJ3173~3175 TJOI2013 DAY2

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());
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值