2014-11-30 01:10:38
总结:比赛时做了两题。
第三题一开始就想到可用线段树什么的优化到n^2log(n),但是由于没有写过这样的题,嫌麻烦就没敲Orz....真是太逗了QAQ
A:暴力
1 /************************************************************************* 2 > File Name: 1001.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Sat 29 Nov 2014 07:00:51 PM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <map> 14 #include <set> 15 #include <stack> 16 #include <queue> 17 #include <iostream> 18 #include <algorithm> 19 using namespace std; 20 #define lp (p << 1) 21 #define rp (p << 1|1) 22 #define getmid(l,r) (l + (r - l) / 2) 23 #define MP(a,b) make_pair(a,b) 24 typedef long long ll; 25 const int INF = 1 << 30; 26 27 int T,N; 28 int num[1100]; 29 30 int main(){ 31 scanf("%d",&T); 32 while(T--){ 33 int a; 34 memset(num,0,sizeof(num)); 35 scanf("%d",&N); 36 for(int i = 1; i <= N; ++i){ 37 scanf("%d",&a); 38 num[a]++; 39 } 40 int tmax = 0; 41 for(int i = 1; i <= N; ++i){ 42 tmax = max(tmax,num[i]); 43 } 44 for(int i = 1; i <= N; ++i){ 45 if(num[i] == tmax){ 46 printf("%d\n",i); 47 break; 48 } 49 } 50 } 51 return 0; 52 }
B:cf、上海网络赛都出现过的解法。
开个标记计数数组cnt[],对于每个区间[i,j],cnt[i]++,cnt[j + 1]--,做两个标记。
然后就是扫一遍x轴,维护一个临时变量tmp,每到一个点就加上它的cnt值,再到下一个点... 找出过程中最大的tmp即可
1 /************************************************************************* 2 > File Name: 1002.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Sat 29 Nov 2014 07:03:40 PM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <map> 14 #include <set> 15 #include <stack> 16 #include <queue> 17 #include <iostream> 18 #include <algorithm> 19 using namespace std; 20 #define lp (p << 1) 21 #define rp (p << 1|1) 22 #define getmid(l,r) (l + (r - l) / 2) 23 #define MP(a,b) make_pair(a,b) 24 typedef long long ll; 25 const int INF = 1 << 30; 26 const int maxn = 200010; 27 28 int T,N; 29 int x[maxn],y[maxn],st[maxn]; 30 int add[maxn],cnt; 31 32 int main(){ 33 scanf("%d",&T); 34 while(T--){ 35 cnt = 0; 36 memset(add,0,sizeof(add)); 37 scanf("%d",&N); 38 for(int i = 1; i <= N; ++i){ 39 scanf("%d%d",&x[i],&y[i]); 40 st[++cnt] = x[i]; 41 st[++cnt] = y[i]; 42 } 43 sort(st + 1,st + cnt + 1); 44 int sz = unique(st + 1,st + cnt + 1) - st; 45 for(int i = 1; i <= N; ++i){ 46 int a = lower_bound(st + 1,st + sz + 1,x[i]) - st; 47 int b = lower_bound(st + 1,st + sz + 1,y[i]) - st; 48 add[a]++; 49 add[b + 1]--; 50 } 51 int ans = 0,tmp = 0; 52 for(int i = 1; i <= sz; ++i){ 53 tmp += add[i]; 54 ans = max(ans,tmp); 55 } 56 printf("%d\n",ans); 57 } 58 return 0; 59 }
C:比较明显的线段树/树状数组优化DP.....自己瞎想想的比较歪,最后还建图强行搞成DAG记忆化搜索了 TAT,这YY得我也是醉了。
好了,正解是:dp[i][j]表示前i个球,已经转化了j次的最长长度,然后就是枚举比i小的k,找出最大的dp[k][j] / dp[k][j - 1]。。
还是题解说的比较准确:
我们令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)。
好了,由于数据挺大,离散化下,然后用m颗线段树 or BIT维护前缀最大值,这里用BIT常数更小。
1 /************************************************************************* 2 > File Name: 5125.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Sun 30 Nov 2014 12:18:29 AM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <map> 14 #include <set> 15 #include <stack> 16 #include <queue> 17 #include <iostream> 18 #include <algorithm> 19 using namespace std; 20 #define lp (p << 1) 21 #define rp (p << 1|1) 22 #define getmid(l,r) (l + (r - l) / 2) 23 #define MP(a,b) make_pair(a,b) 24 typedef long long ll; 25 const int INF = 1 << 30; 26 const int maxn = 2010; 27 28 struct BIT{ 29 int c[maxn]; 30 int Lowbit(int x){ 31 return x & (-x); 32 } 33 int Getmax(int x){ 34 int res = 0; 35 while(x > 0){ 36 res = max(res,c[x]); 37 x -= Lowbit(x); 38 } 39 return res; 40 } 41 void Update(int x,int val){ 42 while(x <= maxn){ 43 c[x] = max(c[x],val); 44 x += Lowbit(x); 45 } 46 } 47 }t[maxn]; 48 49 int T,N,M,a[maxn],b[maxn]; 50 int cp[maxn],cnt; 51 52 int main(){ 53 scanf("%d",&T); 54 while(T--){ 55 memset(t,0,sizeof(t)); 56 cnt = 0; 57 scanf("%d%d",&N,&M); 58 for(int i = 1; i <= N; ++i){ 59 scanf("%d%d",a + i,b + i); 60 cp[++cnt] = a[i]; 61 cp[++cnt] = b[i]; 62 } 63 sort(cp + 1,cp + cnt + 1); 64 cnt = unique(cp + 1,cp + cnt + 1) - cp; 65 for(int i = 1; i <= N; ++i){ 66 a[i] = lower_bound(cp + 1,cp + cnt + 1,a[i]) - cp; 67 b[i] = lower_bound(cp + 1,cp + cnt + 1,b[i]) - cp; 68 } 69 int ans = 0; 70 for(int i = 1; i <= N; ++i){ 71 for(int j = M; j >= 0; --j){ 72 int tmp = t[j].Getmax(a[i] - 1) + 1; 73 t[j].Update(a[i],tmp); 74 ans = tmp > ans ? tmp : ans; 75 if(j && j <= M){ 76 tmp = t[j - 1].Getmax(b[i] - 1) + 1; 77 t[j].Update(b[i],tmp); 78 ans = tmp > ans ? tmp : ans; 79 } 80 } 81 } 82 printf("%d\n",ans); 83 } 84 return 0; 85 }