[SDOI2014]LIS

题目描述

给定序列A,序列中的每一项Ai有删除代价Bi和附加属性Ci。请删除若干项,使得4的最长上升子序列长度减少至少1,且付出的代价之和最小,并输出方案。 如果有多种方案,请输出将删去项的附加属性排序之后,字典序最小的一种。

输入输出格式

输入格式:

输入包含多组数据。 输入的第一行包含整数T,表示数据组数。接下来4*T行描述每组数据。 每组数据的第一行包含一个整数N,表示A的项数,接下来三行,每行N个整数A1..An,B1.,Bn,C1..Cn,满足1 < =Ai,Bi,Ci < =10^9,且Ci两两不同。


输出格式:

对每组数据,输出两行。第一行包含两个整数S,M,依次表示删去项的代价和与数量;接下来一行M个整数,表示删去项在4中的的位置,按升序输出。

输入输出样例

输入样例#1:

1
6
3 4 4 2 2 3
2 1 1 1 1 2
6 5 4 3 2 1

输出样例#1:

4 3
    2 3 6
解释:删去(A2,43,A6),(A1,A6),(A2,43,44,A5)等都是合法的方案,但
{A2,43,A6)对应的C值的字典序最小。

说明

1 < =N < =700 T < =5

题意:
给定一个序列,删去若干项,使得序列的 LIS 长度减少,且代价和最小
输出字典序最小的方案

分析:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;

#define FRE(name) freopen(#name".in","r",stdin);freopen(#name".out","w",stdout);

const int N=10005;
const int inf=0x3f3f3f3f;
struct edge{int v,next,cap;}e[N*100];int tot=1,head[N];
struct node{int c,id;}c[N];
int dis[N],q[N*10];
int n,cas,maxflow,maxn,a[N],b[N],f[N],ans[N*10];

inline 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*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
inline bool cmp(const node &x,const node &y){
    return x.c<y.c;
}
inline void add(int x,int y,int z){
    e[++tot].v=y;e[tot].cap=z;e[tot].next=head[x];head[x]=tot;
    e[++tot].v=x;e[tot].cap=0;e[tot].next=head[y];head[y]=tot;
}
inline bool bfs(int S,int T){
    memset(dis,-1,sizeof dis);
    unsigned short h=0,t=1;
    q[t]=S;dis[S]=0;
    while(h!=t){
        int x=q[++h];
        for(int i=head[x];i;i=e[i].next){
            if(e[i].cap && dis[e[i].v]==-1){
                dis[e[i].v]=dis[x]+1;
                if(e[i].v==T) return 1;
                q[++t]=e[i].v;
            }
        }
    }
    return 0;
}
int dfs(int x,int T,int f){
    if(x==T) return f;
    int used=0,t;
    for(int i=head[x];i;i=e[i].next){
        if(e[i].cap && dis[e[i].v]==dis[x]+1){
            t=dfs(e[i].v,T,min(e[i].cap,f));
            e[i].cap-=t;e[i^1].cap+=t;
            used+=t;f-=t;
            if(!f) return used;
        }
    }
    if(!used) dis[x]=-1;
    return used;
}
inline int dinic(int S,int T){
    int res=0;
    while(bfs(S,T)) res+=dfs(S,T,inf);
    return res;
}
void mapping(int S,int T){
    for(int i=1;i<=n;i++) add(i,i+n,b[i]);
    for(int i=1;i<=n;i++) if(f[i]==1) add(S,i,inf);
    for(int i=1;i<=n;i++) if(f[i]==maxn) add(i+n,T,inf);
    for(int i=1;i<=n;i++){
        for(int j=1;j<i;j++){
            if(a[j]<a[i] && f[i]==f[j]+1){
                add(j+n,i,inf);
            }
        }
    }
}
inline void Cl(){
    tot=1;maxn=0;
    memset(head,0,sizeof head);
}
int main(){
    //FRE(lis)
    for(cas=read();cas--;){
        n=read();Cl();
        for(int i=1;i<=n;i++) a[i]=read();
        for(int i=1;i<=n;i++) b[i]=read();
        for(int i=1;i<=n;i++) c[i].c=read(),c[i].id=i;
        for(int i=1;i<=n;i++){
            f[i]=1;
            for(int j=1;j<i;j++){
                if(a[j]<a[i]) f[i]=max(f[i],f[j]+1);
            }
            maxn=max(maxn,f[i]);
        }
        int S=0,T=n<<1|1,cnt=0;
        mapping(S,T);
        maxflow=dinic(S,T);
        sort(c+1,c+n+1,cmp);
        for(int i=1;i<=n;i++){
            int now=c[i].id;
            int u=now,v=now+n;
            if(bfs(u,v)) continue;
            dinic(T,v);dinic(u,S);
            ans[++cnt]=now;
        }
        sort(ans+1,ans+cnt+1);
        printf("%d %d\n",maxflow,cnt);
        for(int i=1;i<cnt;i++) printf("%d ",ans[i]);printf("%d\n",ans[cnt]);
    }
    return 0;
}
时间: 2024-10-19 07:51:00

[SDOI2014]LIS的相关文章

3532: [Sdoi2014]Lis 最小字典序最小割

3532: [Sdoi2014]Lis Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 865  Solved: 311[Submit][Status][Discuss] Description 给定序列A,序列中的每一项Ai有删除代价Bi和附加属性Ci.请删除若干项,使得4的最长上升子序列长度减少至少1,且付出的代价之和最小,并输出方案.如果有多种方案,请输出将删去项的附加属性排序之后,字典序最小的一种. 这题难点在如何求一组最小字典序最小的最小

bzoj千题计划141:bzoj3532: [Sdoi2014]Lis

http://www.lydsy.com/JudgeOnline/problem.php?id=3532 如果没有字典序的限制,那么DP拆点最小割即可 加上字典序的限制: 按c从小到大枚举最小割边集中的边,去掉这条边对网络的影响,继续枚举直至获得最小割边集 判断是不是最小割边集中的边: 在残量网络中边的起点和终点不连通 注:最小割边集中的边一定满流,但满流边不一定是最小割边集中的边 如下图所示,流量为1和3的两条边满流,但最小割边集为流量为4的那条边 去掉一条边对网络的影响: 边:u-->v 这

BZOJ3532: [Sdoi2014]Lis

感谢ZYF神犇的耐心解答-- 如果这题只要求最小代价--那就是一个比较明显的拆点最小割,对于所有\(j<i.a[j]<a[i].f_i=f_j+1\)的\(i\)和\(j\)之间连一条边. 但是题目要求字典序最小,我们要用退流算法. 我们考虑从点\(i\)到\(i'\)的一条满流边,它是最小割中的边当且仅当不能从\(i\)增广到\(i'\). 退流的话也不难,直接从\(T\)到\(i'\)和\(i\)到\(S\)做两次最大流,再删掉\(i\)到\(i'\)这条边. 1 /***********

P3308 [SDOI2014]LIS(最小割+退流)

传送门 设\(f[i]\)为以\(i\)结尾的最长上升子序列.可以考虑建这样一张图,对于所有的\(i<j,f[j]=f[i+1]\)连边\((i,j)\),\(f[i]=1\)的话连边\((S,i)\),\(f[i]=max(f[j])\)的话连边\((j,T)\),然后就是删去若干个点使\(S,T\)不连通并且代价最小,那么拆点最小割就行了 然后是字典序的问题.我们把所有的点按\(c\)排个序然后看看这个点也就是新图中的这条边是否可以在最小割里.只要判断一下残量网络中是否存在\(u\)到\(u

YCB 的暑期计划

前言 YCB现在很弱(TAT) 暑假有一个月,赶快狂补一下. 大概的计划如下: 首先前期会以数据结构为主,毕竟代码能力太弱,涉及内容:线段树分治.二进制分组.KD-Tree. 等数据结构做到没有智商的时候加入一波数论,内容为 杜教筛.min_25筛. 然后中途小清新一下,做一些 组合博弈与构造题. 接着继续练代码能力,顺便学一些神奇的暴力:启发式合并.dsu on tree . 然后图论也忘的差不多了,就回过头去学点新东西,大概会有spfa判负环.0/1分数规划.差分约束. 估计这个时候也没有什

@loj - [email&#160;protected]「SDOI2014」Lis

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 给定序列 A,序列中的每一项 Ai 有删除代价 Bi 和附加属性 Ci 请删除若干项,使得 A 的最长上升子序列长度减少至少 1,且付出的代价之和最小,并输出方案. 如果有多种方案,请输出将删去项的附加属性排序之后,字典序最小的一种. 输入格式 输入包含多组数据. 输入的第一行包含整数

小明系列问题――小明序列(LIS)

小明系列问题――小明序列 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 4521 Description 大家都知道小明最喜欢研究跟序列有关的问题了,可是也就因为这样,小明几乎已经玩遍各种序列问题了.可怜的小明苦苦地在各大网站上寻找着新的序列问题,可是找来找去都是自己早已研究过的序列.小明想既然找不到,那就自己来发明一个新的序列问题吧!

hdu4521 小明系列问题——小明序列(LIS变种 (线段树+单点更新解法))

链接: huangjing 题目:中文题目 思路: 这个题目如果去掉那个距离大于d的条件,那么必然是一个普通的LIS,但是加上那个条件后就变得复杂了.用dp的解法没有看懂,我用的线段树的解法...就是采用延迟更新的做法,用为距离要大于d啊,所以我们在循环到第i的时候,就对(i-d-1)这个点进行更新,因为如果在(i-d-1)这个点更新了,会对后面的造成影响,然后线段树的tree[]数组存的是以i结尾的最长lis,那么每次询问的时候就找最大的tree[]就可以了... 代码: 小明系列问题--小明

RQNOJ 201 奥运大包围:LIS + 拼链成环

题目链接:https://www.rqnoj.cn/problem/201 题意: 开始时n(n<=1000)个人手拉手围成一个圈. 后来这些人中的一些按顺序向里面出圈形成一个新圈.从而使原圈形成一个从高到低,最低与最高连接的圈. 新圈重复相同的操作,直到没有人要出圈为止. 问最少要形成多少个这样的圈. 题解: (1)拼链成环: 对于一个环,可以用两条由环拆开的链拼在一起表示. 例如:有一个环为"1,2,3,4"(1和4连在一起),则可以表示为"1,2,3,4,1,2,