BZOJ3173 最长上升子序列
数从小到大加入,所以以每个数结尾的最大长度等于位置在它前面的数的长度的最大值+1,求每个数的位置的方法同POJ2828.
#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
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());
}