COJ0986:WZJ的数据结构(负十四)

WZJ的数据结构(负十四)
难度级别:D; 运行时间限制:6000ms; 运行空间限制:262144KB; 代码长度限制:2000000B

试题描述

请你设计一个数据结构,完成以下功能:

给定一个大小为N的整数组A,M次操作,操作分两种:

1.1 i j k 每次询问给你i,j,k三个参数,求Ai至Aj中第k小的数。

2.0 x v 每次操作给你x,v两个参数,将A[x]改成v。


输入

第一行为两个正整数N,M。
第二行为N个正整数Ai。
接下来M行为操作。

输出

对于每个询问输出答案(保证k合法)。

输入示例

6 8
1 3 2 2 5 3
1 1 3 2
1 1 4 2
1 1 4 3
1 1 4 4
0 4 3
1 1 4 3
0 2 5
1 1 4 4

输出示例

2
2
2
3
3
5

其他说明

1<=N,M,Ai,v<=100000
1<=i<=j<=N
1<=k<=j-i+1
1<=x<=N
 

写一个二分+树状数组+Treap,挺爽的

#include<cstdio>
#include<cctype>
#include<queue>
#include<ctime>
#include<cstring>
#include<algorithm>
#define rep(s,t) for(int i=s;i<=t;i++)
#define ren for(int i=first[x];i!=-1;i=next[i])
using namespace std;
inline int read() {
    int x=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c==‘-‘) f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-‘0‘;
    return x*f;
}
const int maxn=100010;
const int maxnode=2000010;
struct Node {
    Node* ch[2];
    int r,s,v;
    void maintain() {s=ch[0]->s+ch[1]->s+1;}
}nodes[maxnode],*null=&nodes[0];
queue<Node*> del;
int n,A[maxn],ToT;
Node* newnode(int v) {
    Node* o;
    if(!del.empty()) o=del.front(),del.pop();
    else o=&nodes[++ToT];
    o->ch[0]=o->ch[1]=null;
    o->s=1;o->v=v;o->r=rand();
    return o;
}
void remove(Node* &o) {
    del.push(o);o=null;
}
void rotate(Node* &o,int d) {
    Node* k=o->ch[d^1];o->ch[d^1]=k->ch[d];k->ch[d]=o;
    o->maintain();k->maintain();o=k;
}
void insert(Node* &o,int v) {
    if(o==null) o=newnode(v);
    else {
        int d=v>o->v;insert(o->ch[d],v);
        if(o->ch[d]->r>o->r) rotate(o,d^1);
        else o->maintain();
    }
}
void remove(Node* &o,int v) {
    if(o->v==v) {
        Node* t=o;
        if(o->ch[0]==null) o=o->ch[1],remove(t);
        else if(o->ch[1]==null) o=o->ch[0],remove(t);
        else {
            int d=o->ch[0]->r>o->ch[1]->r;
            rotate(o,d);remove(o->ch[d],v);
        }
    }
    else remove(o->ch[v>o->v],v);
    if(o!=null) o->maintain();
}
void print(Node* o) {
    if(o==null) return;
    print(o->ch[0]);
    printf("%d ",o->v);
    print(o->ch[1]);
}
int query(Node* &o,int v) {
    if(o==null) return 0;
    if(v<=o->v) return query(o->ch[0],v);
    return query(o->ch[1],v)+o->ch[0]->s+1;
}
Node* root[maxn];
void insert(int x,int v) {for(;x<=n;x+=x&-x) insert(root[x],v);}
void update(int x,int v) {for(;x<=n;x+=x&-x) remove(root[x],v);}
int query(int x,int v) {int ret=0;for(;x;x-=x&-x) ret+=query(root[x],v+1);return ret;}
int main() {
    null->s=0;srand(time(0));
    n=read();int m=read();
    rep(1,n) root[i]=null;
    rep(1,n) insert(i,A[i]=read());
    while(m--) {
        if(read()) {
            int l=read(),r=read(),k=read();
            int L=1,R=100000,M;
            while(L<R) if(query(r,M=L+R>>1)-query(l-1,M=L+R>>1)>=k) R=M; else L=M+1;
            printf("%d\n",L);
        }
        else {
            int x=read();update(x,A[x]);
            insert(x,A[x]=read());
        }
    }
    return 0;
}

复习一下树状数组+可持久化线段树,写WA了一发真不爽

#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<algorithm>
#define rep(s,t) for(int i=s;i<=t;i++)
#define ren for(int i=first[x];i!=-1;i=next[i])
using namespace std;
inline int read() {
    int x=0,f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c==‘-‘) f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-‘0‘;
    return x*f;
}
const int maxn=100010;
const int maxnode=20000010;
int ls[maxnode],rs[maxnode],s[maxnode],ToT;
int n,m,A[maxn],root[maxn],c[maxn];
void update(int& y,int x,int l,int r,int pos,int v) {
    s[y=++ToT]=s[x]+v;if(l==r) return;
    int mid=l+r>>1;ls[y]=ls[x];rs[y]=rs[x];
    if(pos<=mid) update(ls[y],ls[x],l,mid,pos,v);
    else update(rs[y],rs[x],mid+1,r,pos,v);
}
void update(int x,int v) {
    for(int i=x;i<=n;i+=i&-i) update(c[i],c[i],1,100000,A[x],-1);
    for(int i=x;i<=n;i+=i&-i) update(c[i],c[i],1,100000,A[x]=v,1);
}
int lt[maxn],rt[maxn],ltot,rtot;
void get(int x,int tp) {
    if(!tp) {lt[ltot=1]=root[x];for(;x;x-=x&-x) if(c[x]) lt[++ltot]=c[x];}
    else {rt[rtot=1]=root[x];for(;x;x-=x&-x) if(c[x]) rt[++rtot]=c[x];}
}
int main() {
    n=read();m=read();
    rep(1,n) update(root[i],root[i-1],1,100000,A[i]=read(),1);
    while(m--) {
        if(!read()) {
            int x=read(),v=read();
            update(x,v);
        }
        else {
            int ql=read(),qr=read(),k=read();
            get(ql-1,0);get(qr,1);int l=1,r=100000;
            while(l<r) {
                int mid=l+r>>1,tot=0;
                rep(1,ltot) tot-=s[ls[lt[i]]];
                rep(1,rtot) tot+=s[ls[rt[i]]];
                if(tot>=k) {
                    r=mid;
                    rep(1,ltot) lt[i]=ls[lt[i]];
                    rep(1,rtot) rt[i]=ls[rt[i]];
                }
                else {
                    l=mid+1;k-=tot;
                    rep(1,ltot) lt[i]=rs[lt[i]];
                    rep(1,rtot) rt[i]=rs[rt[i]];
                }
            }
            printf("%d\n",l);
        }
    }
    return 0;
}

时间: 2024-08-30 12:36:44

COJ0986:WZJ的数据结构(负十四)的相关文章

14. 蛤蟆的数据结构进阶十四排序实现之简单选择排序

14. 蛤蟆的数据结构进阶十四排序实现之简单选择排序 本篇名言:"即是我们是一支蜡烛也应该 " 蜡烛成灰泪始干 " 即使我们只是一根火柴也要在关键时刻有一次闪耀即使我们死后尸骨都腐烂了解也要变成磷火在荒野中燃烧. -- 艾青" 继续来看什么是简单选择排序. 欢迎转载,转载请标明出处: 1.  简单选择排序 设所排序序列的记录个数为n.i取1,2,-,n-1,从所有n-i+1个记录(Ri,Ri+1,-,Rn)中找出排序码最小的记录,与第i个记录交换.执行n-1趟后就完

COJ 1010 WZJ的数据结构(十) 线段树区间操作

传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=1001 WZJ的数据结构(十) 难度级别:D: 运行时间限制:3000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,高效执行以下过程: #include<iostream>using namespace std;const int maxn=100010;int A[maxn];int tp,ql,qr,v;int

COJ 1010 WZJ的数据结构(十) 线段树的地狱

传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=1001 WZJ的数据结构(十) 难度级别:D: 运行时间限制:3000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,高效执行以下过程: #include<iostream>using namespace std;const int maxn=100010;int A[maxn];int tp,ql,qr,v;int

数据结构(十四)——二叉树

数据结构(十四)--二叉树 一.二叉树简介 1.二叉树简介 二叉树是由n(n>=0)个结点组成的有序集合,集合或者为空,或者是由一个根节点加上两棵分别称为左子树和右子树的.互不相交的二叉树组成.二叉树的五种形态: 2.二叉树的存储结构模型 树的另一种表示法:孩子兄弟表示法A.每个结点都有一个指向其第一个孩子的指针B.每个结点都有一个指向其第一个右兄弟的指针孩子兄弟表示法的特性:A.能够表示任意的树形结构B.每个结点包含一个数据成员和两个指针成员C.孩子结点指针和兄弟结点指针构成树杈 3.满二叉树

COJ 0986 WZJ的数据结构(负十四) 区间动态k大

题解:哈哈哈我过了!!!主席树+树状数组写起来还真是hentai啊... 在这里必须分享我的一个沙茶错!!!看这段代码: void get(int x,int d){ if(!d)for(lt[ltot=1]=root[x];x;x-=x&-x)if(c[x])lt[++ltot]=c[x]; else for(rt[rtot=1]=root[x];x;x-=x&-x)if(c[x])rt[++rtot]=c[x];return; } 似乎挺正常是吧?而且缩进也很优美对不对!!! 可是!!

ES6 第十四节 map数据结构

ES6 第十四节 map数据结构 目录 ES6 第十四节 map数据结构 第十四节 map数据结构 Json和map格式的对比 map的增删查 取值get 删除delete 删除delete的特定值: size属性 查找是否存在has 清除所有元素clear 第十四节 map数据结构 在一些构建工具中是非常喜欢使用map这种数据结构来进行配置的,因为map是一种灵活,简单的适合一对一查找的数据结构. Json和map格式的对比 map的效率和灵活性更好 先来写一个JSON,这里我们用对象进行模拟

COJ966 WZJ的数据结构(负三十四)

WZJ的数据结构(负三十四) 难度级别:C: 运行时间限制:20000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 给一棵n个节点的树,请对于形如"u r"的Q个询问, 回答以 u 节点为中心,半径 r 以内的节点中,权值最大的节点的编号是多少.如果有多个节点,返回编号最小的. 输入 共有一组测试数据.第一行包含一个整数 n (1 ≤ n ≤ 10^5),表示节点总数.接下来的一行,包含 n 个数字,表示每个节点的权值 vi (1 ≤ vi ≤ 1

COJ 0970 WZJ的数据结构(负三十)树分治

WZJ的数据结构(负三十) 难度级别:D: 运行时间限制:1000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 给你一棵N个点的无根树,点和边上均有权值.请你设计一个数据结构,回答M次操作. 1 x v:对于树上的每一个节点y,如果将x.y在树上的距离记为d,那么将y节点的权值加上d*v. 2 x:询问节点x的权值. 输入 第一行为一个正整数N.第二行到第N行每行三个正整数ui,vi,wi.表示一条树边从ui到vi,距离为wi.第N+1行为一个正整数M.最后

COJ 0981 WZJ的数据结构(负十九)树综合

WZJ的数据结构(负十九) 难度级别:E: 运行时间限制:15000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 WZJ的数据结构中有很多都是关于树的.这让很多练习模板的同学还要找来找去很不爽,于是WZJ跟小伙伴们一块商量如何将这些题汇拢到一块去: WZJ:为了大家简单,我规定一开始是一棵有根树. LZJ:那我一定得加上换根操作喽. XJR:链信息修改,链信息增加,链信息翻倍,维护链信息的最大,最小,总和肯定很好做. CHX:子树信息修改,子树信息增加,子树