zoukankan      html  css  js  c++  java
  • 洛谷P3332 [ZJOI2013]K大数查询

    题目描述

    有N个位置,M个操作。操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。

    输入输出格式

    输入格式:

    第一行N,M接下来M行,每行形如1 a b c或2 a b c

    输出格式:

    输出每个询问的结果

    输入输出样例

    输入样例#1:

    2 5
    1 1 2 1
    1 1 2 2
    2 1 1 2
    2 1 1 1
    2 1 2 3

    输出样例#1:

    1
    2
    1

    说明

    【样例说明】

    第一个操作 后位置 1 的数只有 1 , 位置 2 的数也只有 1 。 第二个操作 后位置 1

    的数有 1 、 2 ,位置 2 的数也有 1 、 2 。 第三次询问 位置 1 到位置 1 第 2 大的数 是

    1 。 第四次询问 位置 1 到位置 1 第 1 大的数是 2 。 第五次询问 位置 1 到位置 2 第 3

    大的数是 1 。

    N,M<=50000,N,M<=50000

    a<=b<=N

    1操作中abs(c)<=N

    2操作中c<=long long

    题解

    权值线段树套下标线段树。
    标记永久化写残了+空间小了,WA/RE了几发

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <vector>
    inline int max(int a, int b){return a > b ? a : b;}
    inline int min(int a, int b){return a < b ? a : b;}
    inline void swap(int &x, int &y){int  tmp = x;x = y;y = tmp;}
    inline void read(long long &x)
    {
        x = 0;char ch = getchar(), c = ch;
        while(ch < '0' || ch > '9') c = ch, ch = getchar();
        while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
        if(c == '-') x = -x;
    }
    const int INF = 0x3f3f3f3f;
    const int MAXN = 100000;
    
    struct NodeY
    {
    	int ls, rs;
    	long long add, sum;
    }nodeY[(MAXN << 7) + 100];
    struct NodeX
    {
    	int root;
    }nodeX[(MAXN << 4) + 100];
    long long n, q, cnt, ma, tmp1, tmp2, tmp3, tmp4;
     
    void modifyY(int ll, int rr, int &o, int l = 1, int r = n)
    {
    	if(!o) o = ++ cnt;
    	if(ll <= l && rr >= r)
    	{
    		++ nodeY[o].add, nodeY[o].sum += r - l + 1;
    		return;
    	}
    	nodeY[o].sum += min(r, rr) - max(l, ll) + 1;
    	int mid = (l + r) >> 1; 
    	if(mid >= ll) modifyY(ll, rr, nodeY[o].ls, l, mid);
    	if(mid < rr) modifyY(ll, rr, nodeY[o].rs, mid + 1, r);
    } 
    void modifyX(int ll, int rr, long long p, int o = 1, int l = 1, int r = MAXN * 2 + 1) 
    {
    	modifyY(ll, rr, nodeX[o].root);
    	if(l == r) return;
    	int mid = (l + r) >> 1;
    	if(p <= mid) modifyX(ll, rr, p, o << 1, l, mid);
    	else modifyX(ll, rr, p, o << 1 | 1, mid + 1, r);
    }
    long long askY(int ll, int rr, int o, int l = 1, int r = n)
    {
    	if(!o) return 0;
    	if(ll <= l && rr >= r) return nodeY[o].sum;
    	int mid = (l + r) >> 1, ans = nodeY[o].add * (min(r, rr) - max(l, ll) + 1);
    	if(mid >= ll) ans += askY(ll, rr, nodeY[o].ls, l, mid); 
    	if(mid < rr) ans += askY(ll, rr, nodeY[o].rs, mid + 1, r);
    	return ans;
    }
    int askX(int ll, int rr, long long p, int o = 1, int l = 1, int r = MAXN * 2  + 1)
    {
    	if(l == r) return l;
    	int mid = (l + r) >> 1;
    	long long a = askY(ll, rr, nodeX[o << 1 | 1].root);
    	if(p <= a) return askX(ll, rr, p, o << 1 | 1, mid + 1, r);
    	else return askX(ll, rr, p - a, o << 1, l, mid);
    }
    int main()
    {
    	read(n), read(q);
    	for(int i = 1;i <= q;++ i)
    	{
    		read(tmp1), read(tmp2), read(tmp3), read(tmp4);
    		if(tmp1 == 1) modifyX(tmp2, tmp3, tmp4 + MAXN + 1);
    		else printf("%lld
    ", askX(tmp2, tmp3, tmp4) - MAXN - 1);
    	}
        return 0;
    }
    
  • 相关阅读:
    Android10_内容提供者_内容观察者_标题栏
    Android08_广播接受者_服务
    Android09_远程服务_系统服务_aidl
    Android07_多界面_Activity生命周期
    Android06_getpost提交_文件上传_多线程下载
    Android_handler_网络请求_img框架
    Android开发04
    java 正则表达式验证邮箱
    postman 基本用法
    java 微信申请退款的开发
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/8926708.html
Copyright © 2011-2022 走看看