• 【LOJ】#2174. 「FJOI2016」神秘数


    题解

    这道题的结论很显然= =
    就是暴力求的话,把一个区间的数排一下序,如果当前这个数大于前面所有数的前缀和+1,那么前缀和+1即我们所求的答案

    那么我们设置一个当前答案(初始为1),在主席树上求出来小于这个答案的数的和是多少,设为t,如果t < ans,那么答案就是ans,如果t >= ans,那么设置ans = t + 1

    容易发现,在两次操作之后ans必然翻倍,所以复杂度是(O(M log N log sum a_{i}))

    代码

    #include <bits/stdc++.h>
    #define MAXN 100005
    //#define ivorysi
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define fi first
    #define se second
    using namespace std;
    typedef long long int64;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;char c = getchar();T f = 1;
        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) {putchar('-');x = -x;}
        if(x >= 10) {
    	out(x / 10);
        }
        putchar('0' + x % 10);
    }
    struct node {
        int sum;
        int lc,rc;
    }tr[MAXN * 40];
    int Ncnt,rt[MAXN];
    int N,a[MAXN],M,MK;
    void Insert(const int &x,int &y,int L,int R,int v) {
        y = ++Ncnt;
        tr[y] = tr[x];
        tr[y].sum += v;
        if(L == R) return;
        int mid = (L + R) >> 1;
        if(v <= mid) Insert(tr[x].lc,tr[y].lc,L,mid,v);
        else Insert(tr[x].rc,tr[y].rc,mid + 1,R,v);
    }
    void Init() {
        read(N);
        for(int i = 1 ; i <= N ; ++i) read(a[i]),MK = max(MK,a[i]);
        read(M);
        for(int i = 1 ; i <= N ; ++i) {
    	Insert(rt[i - 1],rt[i],1,MK,a[i]);
        }
    }
    int query(int L,int R,int v) {
        L = rt[L - 1],R = rt[R];
        int l = 1,r = MK,res = 0;
        while(1) {
    	if(l == r) {res += tr[R].sum - tr[L].sum;break;}
    	int mid = (l + r) >> 1;
    	if(v <= mid) {
    	    r = mid;
    	    L = tr[L].lc;R = tr[R].lc;
    	}
    	else {
    	    l = mid + 1;
    	    res += tr[tr[R].lc].sum - tr[tr[L].lc].sum;
    	    L = tr[L].rc;R = tr[R].rc;
    	}
        }
        return res;
    }
    void Solve() {
        Init();
        int L,R;
        while(M--) {
    	read(L);read(R);
    	int ans = 1;
    	while(1) {
    	    int t = query(L,R,ans);
    	    if(t >= ans) ans = t + 1;
    	    else break;
    	}
    	out(ans);enter;
        }
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
        return 0;
    }
    
  • 相关阅读:
    Android学习路径(两)项目文件本身使用场景和文件演示
    A左右ndroid正在使用Uri监视数据库中的更改
    离PACKET_INp获取信息acket data
    curl 命令
    POJ 3177 Redundant Paths POJ 3352 Road Construction(双连接)
    Linux 下一个 Mysql error 2002 错误解决
    图片打水印 缩放 和一个输入流的转换
    qt Qt5开发
    qt 关于Qt中MVC的介绍与使用
    qt mvc3
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9151353.html
Copyright © 2020-2023  润新知