• 【LOJ】#2265. 「CTSC2017」最长上升子序列


    题解

    点了一个新技能叫杨表(事实上集训的时候听过,但是一直不会

    这道题就是让我们找到k个不上升子序列,要求长度加和最大

    我们用杨表去维护,但是由于杨表的行数可能是n的,复杂度会炸
    我们只维护前(sqrt{n})
    有个结论是把杨表排序方式改过来那么我们会得到杨表的转置,我们发现我们只需要求一些列的和就好了,这个转置后的也只需要维护到(sqrt{n})行即可

    二分找每行的插入位置即可(O(nsqrt{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('
    ')
    #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();
    }
    
  • 相关阅读:
    [ACM_数学] 大菲波数 (hdu oj 1715 ,java 大数)
    [ACM_水题] 不要62(hdu oj 2089, 不含62和4的数字统计)
    [ACM_其他] Square Ice (poj1099 规律)
    [ACM_图论] Domino Effect (POJ1135 Dijkstra算法 SSSP 单源最短路算法 中等 模板)
    [ACM_搜索] Triangles(POJ1471,简单搜索,注意细节)
    [ACM_图论] Sorting Slides(挑选幻灯片,二分匹配,中等)
    [ACM_图论] The Perfect Stall 完美的牛栏(匈牙利算法、最大二分匹配)
    [ACM_几何] Metal Cutting(POJ1514)半平面割与全排暴力切割方案
    [ACM_动态规划] 轮廓线动态规划——铺放骨牌(状态压缩1)
    [ACM_数据结构] 竞赛排名
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9811410.html
Copyright © 2020-2023  润新知