山东省选 郁闷的小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<=N,M<=100000,所有出现的书的编码为不大于2147483647的正数。)

输出

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

这是一道平衡树的题目。只是为了练习一下主席树,顺便写了一下。内存占用比平衡树大多了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 1000005
struct node
{
    int val,ch[2],cnt;
}rec[MAXN<<5];
int root[MAXN],num[MAXN],v[MAXN],vsz,tot=0,n,m;
struct opt
{
    char ops[3];
    int l,r,k;
}opz[MAXN];
#define lowbit(x) (x&-x)
void insert(int &now,int pos,int l,int r,int flag)//不要last参数了。
{
    rec[++tot]=rec[now];
    now=tot;
    int temp=now;
    while(l<r)
    {
      int mid=(l+r)>>1;
      if(pos<=mid)
        {
         rec[++tot]=rec[rec[temp].ch[0]];
         rec[temp].ch[0]=tot;
         temp=tot;
         r=mid;
        }
        else
        {
         rec[++tot]=rec[rec[temp].ch[1]];
         rec[temp].ch[1]=tot;
         temp=tot;
         l=mid+1;
        }
    }
    rec[tot].cnt+=flag;
}
int query(int now,int pos,int l,int r)
{
    while(l!=r)
    {
       int mid=(l+r)>>1;
       if(pos<=mid)
        {
            r=mid;
            now=rec[now].ch[0];
        }
        else
        {
            now=rec[now].ch[1];
            l=mid+1;
        }
    }
    return rec[now].cnt;
}
int getans(int x,int pos)
{
    int ans=0;
    while(x>0)
    {
        ans+=query(root[x],pos,1,vsz);
        x-=lowbit(x);
    }
    return ans;
}
void upd(int x,int pos,int flag)
{
    while(x<=n)
    {
        insert(root[x],pos,1,vsz,flag);
        x+=lowbit(x);
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++)
    {
        scanf("%d",&num[i]);
        v[i]=num[i];
    }
    vsz=n;
    for(int i=1;i<=m;i++)
    {
        scanf("%s",opz[i].ops);
        if(opz[i].ops[0]==‘C‘)
        {scanf("%d %d",&opz[i].l,&opz[i].k);
        v[vsz++]=opz[i].k;
        }
        else scanf("%d %d %d",&opz[i].l,&opz[i].r,&opz[i].k);
    }
    sort(v,v+vsz);
    vsz=unique(v,v+vsz)-v;
    for(int i=0;i<n;i++)
    {
        int pos=lower_bound(v,v+vsz,num[i])-v+1;
        upd(i+1,pos,1);
    }
    int t1,t2,t3;
    for(int i=1;i<=m;i++)
    {
        if(opz[i].ops[0]==‘C‘)
        {
            t1=opz[i].l,t2=num[t1-1];
            t2=lower_bound(v,v+vsz,t2)-v+1;
            upd(t1,t2,-1);
            t2=opz[i].k;
            num[t1-1]=t2;
            t2=lower_bound(v,v+vsz,t2)-v+1;
            upd(t1,t2,1);
        }
            else
            {
                t1=opz[i].l,t2=opz[i].r,t3=opz[i].k;
                t3=lower_bound(v,v+vsz,t3)-v+1;
               printf("%d\n",getans(t2,t3)-getans(t1-1,t3));
            }
    }
return 0;
}
时间: 2024-08-21 19:48:04

山东省选 郁闷的小J的相关文章

HUST-1407 郁闷的小J

离线做法:分别处理每个编号上的各种询问和操作,接着就能用树状数组维护. #include <cstdlib> #include <cstdio> #include <cstring> #include <cctype> #include <cmath> #include <algorithm> #include <iostream> #define rep(i, l, r) for(int i=l; i<=r; i+

Sdut 2416 Fruit Ninja II(山东省第三届ACM省赛 J 题)(解析几何)

Time Limit: 5000MS Memory limit: 65536K 题目描写叙述 Haveyou ever played a popular game named "Fruit Ninja"? Fruit Ninja (known as Fruit Ninja HD on the iPad and Fruit Ninja THD for NvidiaTegra 2 based Android devices) is a video game developed by Hal

[08山东省选]2298 石子合并

2298 石子合并 2008年省队选拔赛山东 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Description 在一个操场上摆放着一排N堆石子.现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分. 试设计一个算法,计算出将N堆石子合并成一堆的最小得分. 输入描述 Input Description 第一行是一个数N. 以下N行每行一个数A,表示石子数目. 输出描述 O

【BZOJ2464】【中山市选2009】小明的游戏 最短路水过

题解:最短路pqspfa200ms,一眼题, 另一种想出来没写的做法:二分答案,上界n+m 时间复杂度O(n*m*log(n+m)),二分+深搜看能不能找到t 最短路代码: #include <queue> #include <cstdio> #include <cstring> #include <algorithm> #define N 505 #define NN 251000 #define inf 0x3f3f3f3f using namespac

python_class_类_对象_自己改编的一个选英雄的小程序

#Author:"haijing"#date:2018/10/24 # c语言在创建变量的时候必须加上变量的类型 如int a=0:#而在python中不用,python原生就是多态的 #python中用的更多的还是封装class Person: def __init__(self, na, gen, age, fig): self.name = na self.gender = gen self.age = age self.fight =fig def show_heros(sel

选第k小元素:分治策略

解析: 1. 将n个元素每5个一组,分成n/5(上界)组. 2. 取出每一组的中位数,任意排序方法,比如插入排序. 3. 递归的调用selection算法查找上一步中所有中位数的中位数,设为x,偶数个中位数的情况下设定为选取中间小的一个. 4. 用x来分割数组,设小于等于x的个数为k,大于x的个数即为n-k. 5. 若i==k,返回x:若i<k,在小于x的元素中递归查找第i小的元素:若i>k,在大于x的元素中递归查找第i-k小的元素. 终止条件:n=1时,返回的即是i小元素. 时间复杂度:O(

[BZOJ 3531] [Sdoi2014] 旅行 【离线+LCT】

题目链接:BZOJ - 3531 题目分析 题目询问一条路径上的信息时,每次询问有某种特定的文化的点. 每个点的文化就相当于一种颜色,每次询问一条路径上某种颜色的点的信息. 可以使用离线算法, 类似于“郁闷的小 J ” 那道题目.将各种操作和询问按照颜色为第一关键字,时间为第二关键字排序. 那么修改颜色的操作就相当于在原颜色中是删点,在新颜色中是加点. 处理完一种颜色的操作后,要将这个颜色的点都做一次删除操作,这样,对于处理下一种颜色,树就又是空的了. 这种题,思考的时候有点晕,写代码的时候非常

HUST 1407(数据结构)

1407 - 郁闷的小J 小J是国家图书馆的一位图书管理员,他的工作是管理一个巨大的书架.虽然他很能吃苦耐劳,但是由于这个书架十分巨大,所以他的工作效率总是很低,以致他面临着被解雇的危险,这也正是他所郁闷的. 具体说来,书架由N个书位组成,编号从1到N.每个书位放着一本书,每本书有一个特定的编码. 小J的工作有两类: 图书馆经常购置新书,而书架任意时刻都是满的,所以只得将某位置的书拿掉并换成新购的书. 小J需要回答顾客的查询,顾客会询问某一段连续的书位中某一特定编码的书有多少本. 例如,共5个书

前端小demo——全选和全不选

模拟购物车,实现全选或者全不选,或者其中任意一件单品单选的效果. 点击顶部复选框实现全选 列表中任意一项未选中,顶部复选框就是未选中的状态 <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <style> * { padding: 0; margin: 0; } #div {