【LOJ】#2265. 「CTSC2017」最长上升子序列
2018-10-18 16:37
197 查看
题解
点了一个新技能叫杨表(事实上集训的时候听过,但是一直不会
这道题就是让我们找到k个不上升子序列,要求长度加和最大
我们用杨表去维护,但是由于杨表的行数可能是n的,复杂度会炸
我们只维护前\(\sqrt{n}\)行
有个结论是把杨表排序方式改过来那么我们会得到杨表的转置,我们发现我们只需要求一些列的和就好了,这个转置后的也只需要维护到\(\sqrt{n}\)行即可
二分找每行的插入位置即可\(O(n\sqrt{n} \log n + k \sqrt{n})\)
代码
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define space putchar(' ') #define enter putchar('\n') #define MAXN 50005 //#define ivorysi using namespace std; typedef long long int64; template<class T> void read(T &res) { res = 0;T f = 1;char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) out(x / 10); putchar('0' + x % 10); } int N,Q,S; int b[MAXN],ans[200005],tr[MAXN]; struct qry_node { int pos,id,k; friend bool operator < (const qry_node &a,const qry_node &b) {return a.pos < b.pos;} }qry[200005]; int lowbit(int x) {return x & (-x);} void Ins(int x,int v) { while(x <= N) { tr[x] += v; x += lowbit(x); } } int Query(int x) { int res = 0; while(x > 0) { res += tr[x]; x -= lowbit(x); } return res; } struct YoungTable { int a[245][MAXN]; int findA(int x,int y,int v) { if(y == 0) return 0; int L = 0,R = y; while(L < R) { int mid = (L + R + 1) >> 1; if(a[x][mid] >= v) L = mid; else R = mid - 1; } return L; } int findB(int x,int y,int v) { if(y == 0) return 0; int L = 0,R = y; while(L < R) { int mid = (L + R + 1) >> 1; if(a[x][mid] < v) L = mid; else R = mid - 1; } return L; } void Insert(int x,int y,int v,bool on) { if(x > S) return; y = min(a[x][0],y); if(!on) y = findA(x,y,v); else y = findB(x,y,v); ++y; if(a[x][y] == 0) { a[x][y] = v;++a[x][0]; if(on) Ins(y,1); } else { int t = a[x][y];a[x][y] = v; Insert(x + 1,y,t,on); } } }A,B; int Calc(int k) { int res = 0; if(k <= S) { for(int i = 1 ; i <= k ; ++i) res += A.a[i][0]; } else { for(int i = 1 ; i <= S ; ++i) res += A.a[i][0]; res += Query(k) - Query(S); } return res; } void Solve() { read(N);read(Q); S = sqrt(N); for(int i = 1 ; i <= N ; ++i) read(b[i]); for(int i = 1 ; i <= Q ; ++i) { qry[i].id = i;read(qry[i].pos);read(qry[i].k); } sort(qry + 1,qry + Q + 1); int p = 1; for(int i = 1 ; i <= N ; ++i) { A.Insert(1,N + 1,b[i],0);B.Insert(1,N + 1,b[i],1); while(p <= Q && qry[p].pos == i) { ans[qry[p].id] = Calc(qry[p].k); ++p; } } for(int i = 1 ; i <= Q ; ++i) {out(ans[i]);enter;} } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }
相关文章推荐
- 【模版】二分查找、最长上升子序列(LIS)、最长下降子序列模版
- POJ1631——Bridging signals(动态规划,最长上升子序列应用)
- 【序列型DP】最长严格上升子序列
- 百练2757:最长上升子序列
- 【POJ2533】Longest Ordered Subsequence(LIS-最长上升子序列/DP)
- Lintcode--010(最长上升子序列)
- HDU 5773 The All-purpose Zero (DP最长上升子序列)
- CSU 1807: 最长上升子序列~ 分类讨论
- 最长上升子序列LIS模板
- HDU 1069 Monkey and Banana(dp最长上升子序列)
- 最长上升和下降子序列好题
- 算法基础之python实现动态规划中数字三角形和最长上升子序列问题
- 最长上升子序列LIS算法粗略讲解
- 最长上升子序列
- PAT L2-014. 列车调度 最长上升子序列
- 最长上升子序列LIS
- codeforces340D - Bubble Sort Graph dp + 最长上升子序列
- POJ 3903 Stock Exchange 最长上升子序列 模板题
- 动态规划——求最长下降/上升子序列
- 最长上升子序列。百炼2757 2种方法