zoukankan      html  css  js  c++  java
  • 【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();
    }
    
  • 相关阅读:
    Good Bye 2014 B. New Year Permutation(floyd )
    hdu 5147 Sequence II (树状数组 求逆序数)
    POJ 1696 Space Ant (极角排序)
    POJ 2398 Toy Storage (叉积判断点和线段的关系)
    hdu 2897 邂逅明下 (简单巴什博弈)
    poj 1410 Intersection (判断线段与矩形相交 判线段相交)
    HDU 3400 Line belt (三分嵌套)
    Codeforces Round #279 (Div. 2) C. Hacking Cypher (大数取余)
    Codeforces Round #179 (Div. 2) B. Yaroslav and Two Strings (容斥原理)
    hdu 1576 A/B (求逆元)
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9811410.html
Copyright © 2011-2022 走看看