magic balls

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 323    Accepted Submission(s): 90

Problem Description
The town of W has N people. Each person takes two magic balls A and B every day. Each ball has the volume ai and bi. People often stand together. The wizard will find the longest increasing subsequence in the ball A. The wizard has M energy. Each point of energy can change the two balls’ volume.(swap(ai,bi)).The wizard wants to know how to make the longest increasing subsequence and the energy is not negative in last. In order to simplify the problem, you only need to output how long the longest increasing subsequence is.
 
Input
The first line contains a single integer T(1≤T≤20)(the data for N>100 less than 6 cases), indicating the number of test cases.
Each test case begins with two integer N(1≤N≤1000) and M(0≤M≤1000),indicating the number of people and the number of the wizard’s energy. Next N lines contains two integer ai and bi(1≤ai,bi≤109),indicating the balls’ volume.
 
Output
For each case, output an integer means how long the longest increasing subsequence is.
 
Sample Input
2
 
 
5 3
5 1
4 2
3 1
2 4
3 1
 
5 4
5 1
4 2
3 1
2 4
3 1
 
Sample Output
4
4
 
 
题意是给两个序列 a , b ..
然后问最多用m次操作( swap(ai,bi) ),使得序列a的最长上升子序列的长度最长
不难想出一个DP就是,dp[i][j][k] 表示最长子序列中最后一个元素是i ,用了j 次操作,k表示元素i有没进行交换(0表示无,1表示有)。
然后转移就是
 
   dp[i][j][0] = max { dp[i][j][0] , dp[k][j][0] }  (  i = 1~ n , j = 0~i , k = 1 ~ i -1 , a[k] < a[i] ) 
   dp[i][j][0] = max { dp[i][j][0] , dp[k][j][1] }  (  i = 1~ n , j = 0~i , k = 1 ~ i -1 , b[k] < a[i] ) 
   dp[i][j][1] = max { dp[i][j][1] , dp[k][j-1][0] }  (  i = 1~ n , j = 0~i-1 , k = 1 ~ i -1 , a[k] < b[i] ) 
   dp[i][j][1] = max { dp[i][j][1] , dp[k][j-1][1] }  (  i = 1~ n , j = 0~i , k = 1 ~ i -1 , b[k] < b[i] ) 
 
O(n)枚举状态第一维 , O(n)枚举状态第二维。
再用线段树或者树状数组O(log n)来更新状态就行了。
用m棵线段树,每棵线段树表示用了j次操作( j = 0~m ) 。
每棵线段树的每个叶子结点的位置表示数值的大小,区间l~r维护的是l~r数值范围dp的最大值。
那么先将a,b序列离散后,数值范围是0~2000。
 
然后当我们要更新 dp[i][j][0] 的时候,就第j棵线段树找出1~a[i]-1的结点中,用dp的最大值+1 去更新。
dp[i][j][1],就第j - 1 棵线段树找出1~b[i]-1的结点中,用dp的最大值+1 去更新。
 
注意。假设我们已经维护出dp[i][j][k] , 先不要把状态插入线段树,因为有可能影响到dp[i][j+1][k]的更新。
那么,在更新dp[i+1][][] 之前 , 把dp[i][][]的所有状态插进线段树就不会影响到更新了。
 
 
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <algorithm> using namespace std; #define root 1,n<<1|1,1
#define lr rt<<1
#define rr rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define X first
#define Y second
typedef long long LL;
typedef pair<int,int> pii;
const int N = ;
const int M = ;
const int inf = 1e9+; int n , m , a[N] , b[N] ; //----------------------------
int date[N][M<<]; void Up( int id , int rt ) {
date[id][rt] = max( date[id][lr] , date[id][rr] ) ;
} void Build( int id , int l , int r , int rt ) {
date[id][rt] = ;
if( l == r ) return ;
int mid = (l+r)>>;
Build(id,lson),Build(id,rson);
Up(id,rt);
} void Update( int id , int l , int r , int rt , int x , int val ) {
if( l == r ) {
date[id][rt] = max( date[id][rt] , val ) ;
return ;
}
int mid = (l+r)>>;
if( x <= mid ) Update(id,lson,x,val);
else Update(id,rson,x,val);
Up(id,rt);
} int Query( int id , int l , int r , int rt , int L , int R ) {
if( l == L && r == R ) {
return date[id][rt];
}
int mid = (l+r)>>;
if( R <= mid ) return Query(id,lson,L,R);
else if( L > mid ) return Query(id,rson,L,R);
else return max( Query(id,lson,L,mid) , Query(id,rson,mid+,R) );
}
//---------------------------------- struct node { int x , id , xx ; }e[N<<];
bool cmp1( const node &a , const node &b ) { return a.x < b.x ; }
bool cmp2( const node &a , const node &b ) { return a.id < b.id ; } void Read() {
cin >> n >> m ;
for( int i = ; i < * n ; ++i ){
cin >> e[i].x ; e[i].id = i ;
}
sort( e , e + * n , cmp1 );
e[].xx = ;
for( int i = ; i < * n ; ++i ){
e[i].xx = ( e[i].x == e[i-].x ? e[i-].xx : e[i-].xx + );
}
sort( e , e + * n , cmp2 );
int tot = ;
for( int i = ; i <= n ; ++i ) a[i] = e[tot++].xx , b[i] = e[tot++].xx ; } vector<pii>A,B; void Run() {
int ans = ;
for( int i = ; i <= m ; ++i ) Build( i , root );
for( int i = ; i <= n ; ++i ) {
A.clear() , B.clear();
for( int j = ; j <= min( i , m ) ; ++j ) {
int tmpa = Query( j , root , , a[i] - ) + ;
ans = max( ans , tmpa ) ; A.push_back(pii(j,tmpa));
if( !j ) continue ;
int tmpb = Query( j - , root , , b[i] - ) + ;
ans = max( ans , tmpb ) ; B.push_back(pii(j,tmpb));
}
for( int j = ; j < A.size() ; ++j ) Update( A[j].X ,root , a[i] , A[j].Y );
for( int j = ; j < B.size() ; ++j ) Update( B[j].X ,root , b[i] , B[j].Y );
}
cout << ans << endl ;
} int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif // LOCAL
ios::sync_with_stdio(false);
int _ ; cin >> _ ;
while( _-- ) Read() , Run() ;
}

HDU 5125 magic balls(线段树+DP)的更多相关文章

  1. hdu 5125 magic balls

    题意:求a数组的LIS,但是加了一个条件,为了LIS最大 b[i] a[i]可以交换.最多交换m次: 思路:我们令dp[i][j][l]表示i在最长上升子序列中,已经损失j点能量,第i个人转换了ai和 ...

  2. HDU 3016 Man Down (线段树+dp)

    HDU 3016 Man Down (线段树+dp) Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Ja ...

  3. Tsinsen A1219. 采矿(陈许旻) (树链剖分,线段树 + DP)

    [题目链接] http://www.tsinsen.com/A1219 [题意] 给定一棵树,a[u][i]代表u结点分配i人的收益,可以随时改变a[u],查询(u,v)代表在u子树的所有节点,在u- ...

  4. hdu 5700区间交(线段树)

    区间交 Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submiss ...

  5. Snacks HDU 5692 dfs序列+线段树

    Snacks HDU 5692 dfs序列+线段树 题意 百度科技园内有n个零食机,零食机之间通过n−1条路相互连通.每个零食机都有一个值v,表示为小度熊提供零食的价值. 由于零食被频繁的消耗和补充, ...

  6. hdu 4117 GRE Words (ac自动机 线段树 dp)

    参考:http://blog.csdn.net/no__stop/article/details/12287843 此题利用了ac自动机fail树的性质,fail指针建立为树,表示父节点是孩子节点的后 ...

  7. hdu 4521 小明系列问题——小明序列(线段树+DP或扩展成经典的LIS)

    小明系列问题--小明序列 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Tot ...

  8. HDU 4719Oh My Holy FFF 线段树+DP

    /* ** 日期: 2013-9-12 ** 题目大意:有n个数,划分为多个部分,假设M份,每份不能多于L个.每个数有一个h[i], ** 每份最右边的那个数要大于前一份最右边的那个数.设每份最右边的 ...

  9. hdu 4747 线段树/DP

    先是线段树 可以知道mex(i,i),mex(i,i+1)到mex(i,n)是递增的. 首先很容易求得mex(1,1),mex(1,2)......mex(1,n) 因为上述n个数是递增的. 然后使用 ...

随机推荐

  1. JVM(17)之 准备-解析-初始化

    开发十年,就只剩下这套架构体系了! >>>   在类加载机制的五个阶段中,我们已经讲完了第一个阶段.剩下的四个阶段由于涉及到比较多的类文件相关的知识,现在讲了会看得很吃力,所以我们暂 ...

  2. vue 移动端列表筛选功能实现

    最近兴趣所致,打算使用vant搭建一个webapp,由于需要使用列表筛选,没有找到合适组件,于是写了一个简单的功能,权当记录. 效果如下:        HTML: <div class=&qu ...

  3. unity DOTween Pro的使用--简化流程--自动播放

    当gameobject setActive(true)的时候自动播放动画 1) 添加DoTween Animation. 设置动画效果, 略 选中 AutoPlay, 取消 AutoKill 2) 在 ...

  4. kali Linux 入门(一)

    一.描述 1.基于Debian Linux 发行版 2013年3月13日 2.包含约600个安全工具 3.定制 安全稳定的内核 4.前身是BackTrack(2013年停止维护) 5.官方机构:Off ...

  5. 工欲善其事,必先利其器——React Native的 IDE

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/yayayaya20122012/article/details/51119801之前的文章中,我们已 ...

  6. Ansible用法playbook

    playbook文件 hello.yml --- - name: test_tasks [各个任务的总描述] hosts: webserver remote_user: root gather_fac ...

  7. spring的统一进行异常处理

    public class ExceptionHandler extends SimpleMappingExceptionResolver { private static final Logger l ...

  8. ResourceBundle读取配置文件

    import java.util.ResourceBundle; /** * Created by win7 on 2017/5/20. */public class Test1 { public s ...

  9. Java IO流总结(二)-示例

    1.使用文件操作的9大方法完成文件的判断 判断文件或目录是否存在 : exits() 返回值boolean型 * 判断是否是文件: isFile() boolean * 判断是否是目录: isDiec ...

  10. IDEA使用中的快捷键

    项目与项目之间的跳转: Ctrl+Alt+]             下一个窗口. Ctrl+Alt+[             跳转回上一个窗口. 文件之间的跳转: Ctrl+E.          ...