hdu 5125 magic balls

题意:求a数组的LIS,但是加了一个条件,为了LIS最大 b[i] a[i]可以交换。最多交换m次;

思路:我们令dp[i][j][l]表示i在最长上升子序列中,已经损失j点能量,第i个人转换了ai和bi的最长上升子序列的数目,可以得到方程 dp[i][j][0]=max{dp[k][j][0](a[k]<a[i])+1,dp[k][j][1](b[k]<a[i])+1},dp[i][j][1]=max(dp[k][j-1][0](a[k]<b[i])+1,dp[k][j-1][1](b[k]<b[i])+1)。这样是n^2k的,我们换个思路,即从k能转移到哪些i,我们先将体积离散化,再用m颗线段树来维护已损失j点能量的情况下体积为某数的最长上升子序列。这样可以做到nlgnk,不过线段树常数写的很大的话还是会TLE,考虑到求最大值实际上是求1~x的最大值,这样我们可以通过常数非常小的树状数组来解决。

 1 #include <cstdio>

 2 #include <cstring>

 3 #include <algorithm>

 4 #define maxn 20000

 5 using namespace std;

 6 

 7 int n,m;

 8 int a[1001],b[1001];

 9 int dp[1001][1001][2];

10 int c[1001][2000];

11 int f[2001],cnt;

12 

13 inline int Find(int xx)

14 {

15     return lower_bound(f,f+cnt,xx)-f+1;

16 }

17 

18 inline void insert(int *c,int x,int cc)

19 {

20     for(; x<=cnt; x+=x&-x)

21     {

22         c[x]=max(c[x],cc);

23     }

24 }

25 

26 inline int get_max(int *c,int x)

27 {

28     int ans=0;

29     for( ; x; x-=x&-x)

30     {

31         ans=max(ans,c[x]);

32     }

33     return ans;

34 }

35 

36 int main()

37 {

38     int T;

39     scanf("%d",&T);

40     while(T--)

41     {

42     

43         int n,m;

44         scanf("%d%d",&n,&m);

45         cnt=0;

46         for(int i=1;i<=n;++i)

47         {

48             scanf("%d%d",a+i,b+i);

49             f[cnt++]=a[i];

50             f[cnt++]=b[i];

51         }

52         sort(f,f+cnt);

53         cnt=unique(f,f+cnt)-f;

54         for(int i=1;i<=n;++i) 

55         {

56             a[i]=Find(a[i]);

57             b[i]=Find(b[i]);

58         }

59         memset(c,0,sizeof(c));

60         int ans=0;

61         for(int i=1;i<=n;++i)

62         {

63             for(int j=0;j<=min(m,i);++j)

64             {

65                 dp[i][j][0]=get_max(c[j],a[i]-1)+1;

66                 ans=max(ans,dp[i][j][0]);

67                 if(j)

68                 {

69                     dp[i][j][1]=get_max(c[j-1],b[i]-1)+1;

70                     ans=max(ans,dp[i][j][1]);

71                 }

72             }

73             for(int j=0;j<=min(m,i);++j)

74             {

75                 insert(c[j],a[i],dp[i][j][0]);

76                 if(j) insert(c[j],b[i],dp[i][j][1]);

77             }

78         }

79         printf("%d\n",ans);

80     }

81     return 0;

82 }
View Code

 

你可能感兴趣的:(HDU)