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. Dubbo源码学习总结系列二 dubbo-rpc远程调用模块

    dubbo本质是一个RPC框架,我们首先讨论这个骨干中的骨干,dubbo-rpc模块. 主要讨论一下几部分内容: 一.此模块在dubbo整体框架中的作用: 二.此模块需要完成的需求功能点及接口定义: ...

  2. 脚本_检测mysql存活状态

    #!bin/bash#功能:检测mysql服务是否存活#作者:liusingbon# host为你需要检测的mysql主机的IP 地址,user为mysql账户名,passwd为密码; 这些信息需要根 ...

  3. spring cloud学习笔记二 ribbon负载均衡

    Ribbon是Netflix发布的负载均衡器,它有助于控制HTTP和TCP的客户端的行为.为Ribbon配置服务提供者地址后,Ribbon就可基于某种负载均衡算法,自动地帮助服务消费者去请求.Ribb ...

  4. ubuntu安装Scala

    参考地址:https://blog.csdn.net/qq_36743482/article/details/78317549 1.下载Scala:http://www.scala-lang.org/ ...

  5. PHP 配置多站点多目录

    Apache配置httpd.conf #增加监听端  可以通过netstat -n -a查看端口是否开启# Listen: Allows you to bind Apache to specific ...

  6. uCOS的软件定时器、uCOS时钟节拍和滴答定时器的关系

    uCOS2.81后的版本中有软件定时器的概念,如果要开启定时器任务,需要在OS_CFG.H文件中 #define  OS_TMR_EN                 1 软件定时器其实跟硬件中断是相 ...

  7. iPython清屏命令

    !clear for Unix-like systems !CLS for Windows

  8. 【leetcode】543. Diameter of Binary Tree

    题目如下: 解题思路:最长的周长一定是树中某一个节点(不一定是根节点)的左右子树中的两个叶子节点之间的距离,所以最简单的办法就是把树中所有节点的左右子树中最大的两个叶子节点之间的距离求出来,最终得到最 ...

  9. $emit 和 $on 进行平行组件之间的传值

    效果图: 注:$emit 和 $on 的事件必须在一个公共的实例上,才能够触发: $emit 触发 $on 接收 需求: 1.有A.B.C三个组件,同时挂载到入口组件中: 2.将A组件中的数据传递到C ...

  10. 【优化】Java开发中注意内存问题,影响JVM

    1. 尽量在合适的场合使用单例 使用单例可以减轻加载的负担,缩短加载的时间,提高加载的效率,但并不是所有地方都适用于单例,简单来说,单例主要适用于以下三个方面: 第一,控制资源的使用,通过线程同步来控 ...