微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

BZOJ 3110ZJOI K大数查询-线段树套线段树

3110: [Zjoi2013]K大数查询

Time Limit: 20 Sec   Memory Limit: 512 MB
Submit: 1785   Solved: 816
[ Submit][ Status][ Discuss]

Description

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

Input

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

Output

输出每个询问的结果

Sample Input

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

Sample Output

1
2
1

HINT

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

a<=b<=N

1操作中abs(c)<=N

2操作中abs(c)<=Maxlongint

裸线段树套线段树:题解给的是外层权值线段树,内层区间线段树。我的理解是,外层权值线段树[L,R] 表示 插入的节点的权值,对于插入x权值的节点,我们对此节点建立一棵区间线段树,如果说我想在[a,b]区间插入x权的数,那么就是在此线段树中查找[a,b]区间使[a,b]区间value域+=b-a+1;此题可切;不过代码写的不怎么快,比标准代码慢了3倍左右,内存使用的也比较多!!谁来帮我优化!!

931816   3110 Accepted 314724 kb 15624 ms C++/Edit 2493 B 2015-04-13 23:06:57
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define N 20010900
#define M 50009
int n,m,nodeID;
int value[N],tag[N],ls[N],rs[N],root[4*M+10];
void push_up(int id) {
    value[id] = 0;
    value[id] += value[ls[id]];
    value[id] += value[rs[id]];
}
void push_down(int id,int l,int r) {
    if(tag[id] == 0)  return;
    if(ls[id]==0) ls[id] = ++nodeID;
    if(rs[id]==0) rs[id] = ++nodeID;
    int mid = ( l + r ) >> 1;
    value[ls[id]] += tag[id]*(mid - l + 1);
    value[rs[id]] += tag[id]*(r - mid);
    tag[ls[id]] += tag[id];
    tag[rs[id]] += tag[id];
    tag[id] = 0;
}
void addY(int &id,int r,int L,int R) {
    if(id == 0) id = ++nodeID;
    if(L<=l&&R>=r){ value[id] += (r-l+1); tag[id]++; return; }
    int mid = ( l + r ) >> 1;
    push_down(id,l,r);
    if(L<=mid) addY(ls[id],mid,L,R);
    if(R>mid)  addY(rs[id],mid+1,r,R);
    push_up(id);
}
int quaryY(int id,int R) {
    if(id == 0) return 0;
    if(L<=l&&R>=r) return value[id];
    int mid = ( l + r ) >> 1;
    int tem = 0;
    push_down(id,r);
    if(L<=mid) tem += quaryY(ls[id],R);
    if(R>mid)  tem += quaryY(rs[id],R);
    return tem;
}
void addX(int x,int id,int R){
    addY(root[id],1,n,R);
    if(l == r) return;
    int mid = ( l + r ) >> 1;
    if(x<=mid) addX(x,id<<1,R);
    else       addX(x,id<<1|1,R);
}
int quaryX(int k,int R){
    if(l==r) return l;
    int tem = quaryY(root[id<<1],R);
    int mid = (l + r)>>1;
    if(tem>=k) return quaryX(k,R);
    else       return quaryX(k-tem,R);
}
void init() {
    nodeID = 1;
    memset(root,sizeof(root));
    memset(tag,sizeof(tag));
    memset(ls,sizeof(ls));
    memset(rs,sizeof(rs));
    memset(value,sizeof(value));
}
int main() {
    int flag,a,b,v;
    //freopen("sequence9.in","r",stdin);
    //freopen("out.txt","w",stdout);
    while(~scanf("%d%d",&n,&m)) {
        init();
        for(int i = 1;i<=m;i++) {
            scanf("%d%d%d%d",&flag,&a,&b,&v);
            if(flag == 1) addX(M-v,2*M,b);
            else          printf("%d\n",M-quaryX(v,b));
        }
    }
    return 0;
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐