方伯伯在自己的农田边散步,他突然发现田里的一排玉米非常的不美。
这排玉米一共有N株,它们的高度参差不齐。
方伯伯认为单调不下降序列很美,所以他决定先把一些玉米拔高,再把破坏美感的玉米拔除掉,使得剩下的玉米的高度构成一个单调不下降序列。
方伯伯可以选择一个区间,把这个区间的玉米全部拔高1单位高度,他可以进行最多K次这样的操作。拔玉米则可以随意选择一个集合的玉米拔掉。
问能最多剩多少株玉米,来构成一排美丽的玉米。
标签:class 编号 根据 mes ram fir lin ssi contains
2018CCPC网络赛
InputThe first line of the input contains an integer TT (1≤T≤10)(1≤T≤10),which is the number of test cases.
In each case, the first line of the input contains an integer NN (1≤N≤105)(1≤N≤105).The following NN lines, the kk-th line contains 3 integers, xk,yk,vkxk,yk,vk (0≤vk≤103)(0≤vk≤103), which indicate that there is a village on (xk,yk)(xk,yk) and he can get vkvk dollars in that village.
The positions of each village is distinct.OutputThe maximum of dollars YJJ can get.Sample Input
1 3 1 1 1 1 2 2 3 3 1
Sample Output
3
就是现在有一个棋盘,你可以向右或者向下走,如果向右下的话就可以得到积分
dp方程就是这样dp[i][j] = max{dp[i-1][j],dp[i][j-1],dp[i-1][j-1]+v[i][j]},
可以用BIT去维护这个dp
但是点很多啊,也许又长又宽,但是能到的点和这个是无关的,所以可以离散化
为啥要离散化呢,因为有T组啊,但是放不离散化的代码AC就很不良心了吧
离散化可以先把y读入,并排序去除相同部分,所以每个的y都可以通过二分找到其位置并进行编号,所以根据其x和y和排序就可以进行了
每次找的过程都是在维护这个区间,dp[i]表示第到第a[i].y列的最大值,
因为我是排序了的,所以设置一个pos去更新的话,一定是t[pos].x<=t[i].x,所以我们在pos需要的地方更新,另外y已经被我们编号了,所以t[pos].y的值是可以去更新的,所以就做完了
#include <bits/stdc++.h> using namespace std; const int N=1e5+5; struct T { int x,y,v; } t[N]; bool cmp(T a, T b) { return a.x<b.x; } int a[N],c[N]; int tot; void update(int i, int val) { for(; i<=tot; i+=i&(-i))c[i]=max(c[i], val); } int query(int i) { int res=0; for(; i>0; i-=i&(-i))res = max(res, c[i]); return res; } int dp[N]; int main() { int T,n; scanf("%d", &T); while (T--) { scanf("%d", &n); for(int i=0; i<n; i++)scanf("%d%d%d",&t[i].x,&t[i].y,&t[i].v); tot=0,memset(c,0,sizeof c); for(int i=0; i<n; i++)a[tot++]=t[i].y; sort(a,a+tot); tot=unique(a,a+tot)-a; for(int i=0; i<n; i++)t[i].y=lower_bound(a,a+tot,t[i].y)-a+1; sort(t,t+n,cmp); for(int i=0; i<n; i++) dp[i]=t[i].v; int pos=0,ans=0; for(int i=0; i<n; i++) { while(pos<i&&t[pos].x!=t[i].x)update(t[pos].y,dp[pos]),pos++; dp[i]=query(t[i].y-1)+t[i].v,ans=max(ans,dp[i]); } printf("%d\n",ans); } return 0; }
方伯伯在自己的农田边散步,他突然发现田里的一排玉米非常的不美。
这排玉米一共有N株,它们的高度参差不齐。
方伯伯认为单调不下降序列很美,所以他决定先把一些玉米拔高,再把破坏美感的玉米拔除掉,使得剩下的玉米的高度构成一个单调不下降序列。
方伯伯可以选择一个区间,把这个区间的玉米全部拔高1单位高度,他可以进行最多K次这样的操作。拔玉米则可以随意选择一个集合的玉米拔掉。
问能最多剩多少株玉米,来构成一排美丽的玉米。
第1行包含2个整数n,K,分别表示这排玉米的数目以及最多可进行多少次操作。
第2行包含n个整数,第i个数表示这排玉米,从左到右第i株玉米的高度ai。
输出1个整数,最多剩下的玉米数。
1 < N < 10000,1 < K ≤ 500,1 ≤ ai ≤5000
数组可以选择k个区间+1,让这个最长不下降序列最长
f[i][j]表示前i个数,用j次区间+1的LIS长度
那我们可以考虑你最优的操作是什么,就是包含最后一个数字,所以可以倒着就行求解
#include<stdio.h> #include<algorithm> using namespace std; int c[5505][505]; int a[10100]; int query(int x,int y) { int ans=0; for(int i=x; i; i-=(i&(-i))) for(int j=y; j; j-=(j&(-j))) ans=max(ans,c[i][j]); return ans; } inline void add(int x,int y,int val) { for(int i=x; i<5505; i+=(i&(-i))) for(int j=y; j<505; j+=(j&(-j))) c[i][j]=max(c[i][j],val); } int main() { int n,m; scanf("%d%d",&n,&m),m++; for(int i=1; i<=n; i++)scanf("%d",&a[i]); int ans=0; for(int i=1; i<=n; i++) for(int j=m,t; j; j--) { t=query(a[i]+j,j)+1,ans=max(ans,t); add(a[i]+j,j,t); } printf("%d\n",ans); }
标签:class 编号 根据 mes ram fir lin ssi contains
原文地址:https://www.cnblogs.com/BobHuang/p/9612685.html