洛谷P2464 [SDOJ2008]郁闷的小J

题目描述

小J是国家图书馆的一位图书管理员,他的工作是管理一个巨大的书架。虽然他很能吃苦耐劳,但是由于这个书架十分巨大,所以他的工作效率总是很低,以致他面临着被解雇的危险,这也正是他所郁闷的。

具体说来,书架由N个书位组成,编号从1到N。每个书位放着一本书,每本书有一个特定的编码。

小J的工作有两类:

1.图书馆经常购置新书,而书架任意时刻都是满的,所以只得将某位置的书拿掉并换成新购的书。

2.小J需要回答顾客的查询,顾客会询问某一段连续的书位中某一特定编码的书有多少本。

例如,共5个书位,开始时书位上的书编码为1,2,3,4,5

一位顾客询问书位1到书位3中编码为“2”的书共多少本,得到的回答为:1

一位顾客询问书位1到书位3中编码为“1”的书共多少本,得到的回答为:1

此时,图书馆购进一本编码为“1”的书,并将它放到2号书位。

一位顾客询问书位1到书位3中编码为“2”的书共多少本,得到的回答为:0

一位顾客询问书位1到书位3中编码为“1”的书共多少本,得到的回答为:2

……

你的任务是写一个程序来回答每个顾客的询问。

输入输出格式

输入格式:

第一行两个整数N,M,表示一共N个书位,M个操作。

接下来一行共N个整数数A1,A2…AN,Ai表示开始时位置i上的书的编码。

接下来M行,每行表示一次操作,每行开头一个字符

若字符为‘C’,表示图书馆购进新书,后接两个整数A(1<=A<=N),P,表示这本书被放在位置A上,以及这本书的编码为P。

若字符为‘Q’,表示一个顾客的查询,后接三个整数A,B,K(1<=A<=B<=N),表示查询从第A书位到第B书位(包含A和B)中编码为K的书共多少本。

输出格式:

对每一个顾客的查询,输出一个整数,表示顾客所要查询的结果。

输入输出样例

输入样例#1:

5 5
1 2 3 4 5
Q 1 3 2
Q 1 3 1
C 2 1
Q 1 3 2
Q 1 3 1

输出样例#1:

1
1
0
2

说明

对于40%的数据,1<=N,M<=5000

对于100%的数据,1<=N,M<=100000

对于100%的数据,所有出现的书的编码为不大于2147483647的正数。

题解

  • 我这里的“种类”就是原题的“编码”。。。

  • 对每种书建立一棵平衡树(我用无旋treap),然后一开始往每个平衡树里插坐标(当然要有序插入)。

  • 开一个数组记录每个位置上书的种类。

  • 对于'C'操作,找到这个位置上书的种类,然后在对应平衡树上删去这个坐标。再记录新的种类,在对应平衡树上新增这个坐标。每个平衡树记录的坐标都应该是有序的。

  • 对于'Q'操作,答案是对应平衡树上的B的排名减去(A-1)的排名,所以剩下的区间就是\([A,B]\)。

  • 输入保证书的种类\(<=2^{31}-1\),所以要离散化。。。我只会map。。。而且懒得打离线了。。。所以边读入边离散化。。。离散化在ins函数中体现,及每读入一次就插入(有的话当然不插入)

Code

// It is made by XZZ
#include<cstdio>
#include<algorithm>
#include<map>
#define Fname "lg2464"
using namespace std;
#define rep(a,b,c) for(rg int a=b;a<=c;a++)
#define drep(a,b,c) for(rg int a=b;a>=c;a--)
#define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
#define il inline
#define rg register
#define vd void
#define pr pair<point,point>
#define mp make_pair
typedef long long ll;
il int gi(){
rg int x=0,f=1;rg char ch=getchar();
while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
int seed=666;
il int Rand(){return seed=seed*19260817ll%2147483647;}
typedef struct node* point;
point null;
struct node{
int pos,rand,size;
point ls,rs;
node(int _pos){pos=_pos,rand=Rand(),size=1,ls=rs=null;}
il vd reset(){size=ls->size+rs->size+1;}
il vd del(){if(this!=null)ls->del(),rs->del(),delete this;}
};
point root[100001];
int Book[100001];
il point merge(point a,point b){
if(a==null)return b;
if(b==null)return a;
if(a->rand<b->rand){a->rs=merge(a->rs,b),a->reset();return a;}
else{b->ls=merge(a,b->ls),b->reset();return b;}
}
il pr split(point now,int num){
if(now==null)return mp(null,null);
point ls=now->ls,rs=now->rs;
if(now->ls->size==num){now->ls=null,now->reset();return mp(ls,now);}
if(now->ls->size+1==num){now->rs=null,now->reset();return mp(now,rs);}
if(num<now->ls->size){
pr T=split(now->ls,num);
now->ls=T.second,now->reset();
return mp(T.first,now);
}else{
pr T=split(now->rs,num-now->ls->size-1);
now->rs=T.first,now->reset();
return mp(now,T.second);
}
}
il int getrank(int k,int num){
int res=0,ret=10000000;
point now=root[k];
while(now!=null){
if(num==now->pos)ret=min(ret,res+now->ls->size+1);
if(num<=now->pos)now=now->ls;
else res+=now->ls->size+1,now=now->rs;
}
if(ret==10000000)return res;
else return ret;
}
map<int,int>f;
int INDEX=0;
il vd ins(int num){if(f.find(num)==f.end())f[num]=++INDEX;}
int main(){
int a,b,k,n=gi(),m=gi();
null=new node(0),null->size=0;
rep(i,1,100000)root[i]=null;
rep(i,1,n)scanf("%d",&a),ins(a),Book[i]=f[a],root[Book[i]]=merge(root[Book[i]],new node(i));
char opt;
while(m--){
opt=getchar();while(opt!='C'&&opt!='Q')opt=getchar();
if(opt=='Q'){
a=gi(),b=gi(),k=gi();
ins(k),k=f[k];
printf("%d\n",getrank(k,b)-getrank(k,a-1));
}else{
a=gi(),k=Book[a];
pr T,TT;
T=split(root[k],getrank(k,a)-1);
TT=split(T.second,1);
delete TT.first;
root[k]=merge(T.first,TT.second);
k=gi(),ins(k);
k=Book[a]=f[k];
T=split(root[k],getrank(k,a));
root[k]=merge(T.first,merge(new node(a),T.second));
}
}
rep(i,1,100000)root[i]->del();
delete null;
return 0;
}

另:一组更(luan)强(zao)的样例

输入样例#2:

10 10
1 2 1 3 4 3 1 2 1 6
Q 2 8 1
Q 5 6 3
Q 8 9 2
C 1 2
C 4 2
Q 1 10 2
C 5 2
Q 2 8 2
C 5 1
Q 1 10 1

输出样例#2:

Output
2
1
1
4
4
4

样例解释

1[2 1 3 4 3 1 2]1 6 ans=2

1 2 1 3[4 3]1 2 1 6 ans=1

1 2 1 3 4 3 1[2 1]6 ans=1

2 2 1 2 4 3 1 2 1 6

2 2 1 2 4 3 1 2 1 6

[2 2 1 2 4 3 1 2 1 6]ans=4

2 2 1 2 2 3 1 2 1 6

2[2 1 2 2 3 1 2]1 6 ans=4

2 2 1 2 1 3 1 2 1 6

[2 2 1 2 1 3 1 2 1 6]ans=4

洛谷P2464 [SDOJ2008]郁闷的小J的更多相关文章

  1. 洛谷P2464 [SDOI2008] 郁闷的小j [分块]

    题目传送门 郁闷的小j 题目描述 小J是国家图书馆的一位图书管理员,他的工作是管理一个巨大的书架.虽然他很能吃苦耐劳,但是由于这个书架十分巨大,所以他的工作效率总是很低,以致他面临着被解雇的危险,这也 ...

  2. 2018.09.26 洛谷P2464 [SDOI2008]郁闷的小J(map+vector)

    传送门 本来出题人出出来想考数据结构的. 但是我们拥有map+vector/set这样优秀的STL,因此直接用map离散化,vector存下标在里面二分找答案就行了. 代码: #include< ...

  3. P2464 [SDOI2008]郁闷的小J

    题目描述 小J是国家图书馆的一位图书管理员,他的工作是管理一个巨大的书架.虽然他很能吃苦耐劳,但是由于这个书架十分巨大,所以他的工作效率总是很低,以致他面临着被解雇的危险,这也正是他所郁闷的. 具体说 ...

  4. [SDOI2008]郁闷的小J(分块)

    [SDOI2008]郁闷的小J 题目描述 小J是国家图书馆的一位图书管理员,他的工作是管理一个巨大的书架.虽然他很能吃苦耐劳,但是由于这个书架十分巨大,所以他的工作效率总是很低,以致他面临着被解雇的危 ...

  5. 山东省选 郁闷的小J

    小J是国家图书馆的一位图书管理员,他的工作是管理一个巨大的书架.虽然他很能吃苦耐劳,但是由于这个书架十分巨大,所以他的工作效率总是很低,以致他面临着被解雇的危险,这也正是他所郁闷的. 具体说来,书架由 ...

  6. 【山东省选2008】郁闷的小J 平衡树Treap

    小J是国家图书馆的一位图书管理员,他的工作是管理一个巨大的书架.虽然他很能吃苦耐劳,但是由于这个书架十分巨大,所以他的工作效率总是很低,以致他面临着被解雇的危险,这也正是他所郁闷的.具体说来,书架由N ...

  7. 洛谷P4907【CYH-01】小奔的国庆练习赛 :$A$换$B$ $problem$(DFS,剪枝)

    洛谷题目传送门 顺便提一下题意有一个地方不太清楚,就是如果输出No还要输出最少需要添加多少张牌才能满足要求.蒟蒻考完以后发现四个点Too short on line 2... 比较需要技巧的搜索 既然 ...

  8. 洛谷.1486.[NOI2004]郁闷的出纳员(Splay)

    题目链接 /* BZOJ1503: 3164kb 792ms/824ms(新建节点) 洛谷 : 3.06mb 320ms/308ms(前一个要慢wtf 其实都差不多,但前者好写) 四种操作: A:所有 ...

  9. fhqtreap - Luogu 2464 [SDOI2008]郁闷的小J

    [SDOI2008]郁闷的小JJ 题目描述 小J是国家图书馆的一位图书管理员,他的工作是管理一个巨大的书架.虽然他很能吃苦耐劳,但是由于这个书架十分巨大,所以他的工作效率总是很低,以致他面临着被解雇的 ...

随机推荐

  1. 【模板】Dijkstra总结

    Dijkstra算法使用于跑最短路的算法. 算法思想 假定图是不带负权的有向图或无向图,采用贪心策略,每次扩展一个距离为最短的点,在以这个点为中间点,更新其他的所有点的距离.当所有边权都为正时,由于不 ...

  2. [Python 多线程] RLock可重入锁 (九)

    RLock 可重复锁,是线程相关的锁.同样是线程相关的还有threading.local. 线程A获得可重用锁,并可以多次成功获取,不会阻塞.最后要再线程A中和acquire次数相同的release. ...

  3. WiFi密码忘记了怎么办之解决方案

    随着科技不断进步,网络产品也越来越便宜了.家家户户基本上都有能力装上宽带. 但是有的时候,时间久了,我们可能会忘记密码(密码设置比较复杂的情况下).那么如何找到密码呢? 通常的办法有很多,百度或者Go ...

  4. [转]TortoiseSVN客户端的安装

    TortoiseSVN是windows平台下Subversion的免费开源客户端. 一般我们都是先讲讲服务器的配置,然后再讲客户端的使用,但是在TortoiseSVN上,却可以反过来.因为,如果你的要 ...

  5. shell一次性执行多条命令

    1.每个命令之间用;隔开说明:各命令的执行给果,不会影响其它命令的执行.换句话说,各个命令都会执行,但不保证每个命令都执行成功. 2.每个命令之间用&&隔开说明:若前面的命令执行成功, ...

  6. 前端基础-CSS是什么?

    阅读目录 一. 什么是CSS 二. 为何要用CSS 三. 如何使用CSS 一. 什么是CSS CSS全称Cascading Style Sheet层叠样式表,是专用用来为HTML标签添加样式的. 样式 ...

  7. 数据库事务ACID特性及隔离级别

    数据库ACID特性介绍 1.原子性(Atomic)一个事务被视为一个不可分割的最小工作单元,这个事务里的所有操作要么全部成功执行,要么全都不执行,不能只执行其中的一部分操作.实现事务的原子性,要支持回 ...

  8. iOS 百度地图判断用户是否拖动地图的检测方法

    前言:百度地图API并没有提供移动地图时的回调接口 实现:通过判断当前地图的中心位置是否为用户位置来判断,代码如下 -(void)mapView:(BMKMapView *)mapView regio ...

  9. Caused by: java.lang.ClassNotFoundException: org.springframework.boot.bind.RelaxedPropertyResolver

    Caused by: java.lang.ClassNotFoundException: org.springframework.boot.bind.RelaxedPropertyResolver 这 ...

  10. Java并发编程(七)终结线程

    线程的状态 一个线程会有如下五个状态 1.新建:线程在被创建时会暂时处于这种状态,此时系统为线程分配资源并对其进行初始化 2.就绪:此时线程已经可以运行,只是系统没有为其分配CPU时间. 3.运行:系 ...