As another one of their crazy antics, the N (1 ≤ N ≤ 100,000) cows want Farmer John to race against the clock to answer some of their pressing questions.

The cows are lined up in a row from 1 to N, and each one is holding a sign representing a number, Ai (1 ≤ Ai≤ 1,000,000,000). The cows need FJ to perform Q (1 ≤ Q ≤ 50,000) operations, which can be either of the following:

  • Modify cow i's number to X (1 ≤ X ≤ 1,000,000,000). This will be represented in the input as a line containing the letter M followed by the space-separated numbers i and X.
  • Count how many cows in the range [P, Q] (1 ≤ P ≤ Q ≤ N) have Ai ≤ X (0 ≤ X ≤ 1,000,000,000). This will be represented in the input as a line containing the letter C followed by the space-separated numbers P, Q, and X.

Of course, FJ would like your help.

Input

The first line gives the integers N and Q, and the next N lines give the initial values of Ai. Finally, the next Q lines each contain a query of the form "M i X" or "C P Q X".

Output

Print the answer to each 'C' query, one per line.

Example

Input: 4 6 3 4 1 7 C 2 4 4 M 4 1 C 2 4 4 C 1 4 5 M 2 10 C 1 3 9  Output: 2 3 4 2

题意:给出一段序列,要求有两种操作, 1 修改一个位置的数字, 2 查询一段区间内的小于val的数字有多少个。

sl: 这是区间查询,所以用线段树维护就好了,但是查询小于val的数字有多少个,所以直接随便用一个平衡树求一个rank就好了。 最近刚刚学了SBT.

试了试模板,还是要手敲为妙。 加了挂还是超时,不知道为何。 应该有好方法。 用treap貌似能过?

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <algorithm>
  5 #include <cmath>
  6 
  7 using namespace std;
  8 
  9 const int maxn = ;
 10 
 11 struct Node {
 12     int key, val;
 13     Node(){};
 14     Node(int a, int b) { key = a; val = b; }
 15     bool operator < (Node b)  { return val < b.val; }
 16     bool operator <= (Node b) { return val <= b.val; }
 17     bool operator > (Node b)  { return val > b.val; }
 18     bool operator >= (Node b) { return val >= b.val; }
 19     bool operator == (Node b) { return val == b.val; }
 20     Node operator + (int a) {
 21         return Node(key, val+a) > Node(key, val) ? Node(key, val+a) : Node(key, val-a);
 22     }
 23 };
 24 
 25 int sz[maxn*];
 26 int key[maxn*];
 27 int lch[maxn*];
 28 int rch[maxn*];
 29 int tot;
 30 
 31 template<typename Type>
 32 class SBT
 33 {
 34 public:
 35     SBT() { Clear(); }
 36     void Clear() { root = ; lch[] = rch[] = sz[] = ; }
 37     static void ClearAll() { tot = ; }
 38     int Size() { return sz[root]; }
 39     bool Empty() { return  == sz[root]; }
 40     bool Find(Type k) { return Find(root, k); }
 41     void InsertR(Type k) { Insert(root, k); } // 可重复插入
 42     void Insert(Type k) { if (!Find(k)) Insert(root, k); }
 43     void Delete(Type k) { if (Find(k)) Delete(root, k); }
 44     void DeleteSmaller(Type k) { DeleteSmaller(root, k); }
 45     int GetRank(Type k) { return GetRank(root, k); }
 46     Type GetKth(int k) { return GetKth(root, k); }
 47     Type GetMin() { return GetKth(root, ); }
 48     Type GetMax() { return GetKth(root, Size()); }
 49     Type GetPre(Type k) { return GetPre(root, k); }
 50     Type GetSuc(Type k) { return GetSuc(root, k); }
 51     int GetSmaller(Type k) { return GetSmaller(root, k); } // 返回小于k的元素的个数
 52 
 53 private:
 54     void LeftRotate(int &t) {
 55         int k = rch[t];
 56         rch[t] = lch[k];
 57         lch[k] = t;
 58         sz[k] = sz[t];
 59         sz[t] =  + sz[lch[t]] + sz[rch[t]];
 60         t = k;
 61     }
 62     void RightRotate(int &t) {
 63         int k = lch[t];
 64         lch[t] = rch[k];
 65         rch[k] = t;
 66         sz[k] = sz[t];
 67         sz[t] =  + sz[lch[t]] + sz[rch[t]];
 68         t = k;
 69     }
 70     void Maintain(int &t, bool flag) {
 71         if ( == t) return ;
 72         if (false == flag) {
 73             if (sz[lch[lch[t]]] > sz[rch[t]]) {
 74                 RightRotate(t);
 75             } else if (sz[rch[lch[t]]] > sz[rch[t]]) {
 76                 LeftRotate(lch[t]);
 77                 RightRotate(t);
 78             } else {
 79                 return ;
 80             }
 81         } else {
 82             if (sz[rch[rch[t]]] > sz[lch[t]]) {
 83                 LeftRotate(t);
 84             } else if (sz[lch[rch[t]]] > sz[lch[t]]) {
 85                 RightRotate(rch[t]);
 86                 LeftRotate(t);
 87             } else {
 88                 return ;
 89             }
 90         }
 91         Maintain(lch[t], false);
 92         Maintain(rch[t], true);
 93         Maintain(t, false);
 94         Maintain(t, true);
 95     }
 96     Type GetPre(int t, Type k) {
 97         if ( == k) return k;
 98         if (k <= key[t]) return GetPre(lch[t], k);
 99         Type tmp = GetPre(rch[t], k);
         if (tmp == k) return key[t];
         return tmp;
     }
     Type GetSuc(int t, Type k) {
         if ( == root) return k;
         if (k >= key[t]) return GetSuc(rch[t], k);
         Type tmp = GetSuc(lch[t], k);
         if (tmp == k) return key[t];
         return tmp;
     }
     Type GetKth(int t, int k) {
         if (sz[lch[t]] >= k) return GetKth(lch[t], k);
         if (sz[lch[t]] == k - ) return key[t];
         return GetKth(rch[t], k - sz[lch[t]] - );
     }
     int GetRank(int t, Type k) {
         if ( == t) return ;
         if (k < key[t]) return GetRank(lch[t], k);
         return sz[lch[t]] +  + GetRank(rch[t], k);
     }
     int GetSmaller(int t, Type k) {
         if ( == t) return ;
         if (k <= key[t]) return GetSmaller(lch[t], k);
         return sz[lch[t]] +  + GetSmaller(rch[t], k);
     }
     bool Find(int t, Type k) {
         if ( == t) return false;
         else if (k < key[t]) return Find(lch[t], k);
         else return (key[t] == k || Find(rch[t], k));
     }
     void Insert(int &t, Type k) {
         if ( == t) {
             t = ++tot;
             lch[t] = rch[t] = ;
             sz[t]= ;
             key[t] = k;
             return ;
         }
         sz[t]++;
         if (k < key[t]) Insert(lch[t], k);
         else Insert(rch[t], k);
         Maintain(t, k >= key[t]);
     }
     void DeleteSmaller(int &t , Type k) {
         if ( == t) return ;
         if ( key[t] < k ) {
             t = rch[t];
             DeleteSmaller(t , key);
         } else {
             DeleteSmaller(lch[t] , k);
             sz[t] =  + sz[lch[t]] + sz[rch[t]];
         }
     }
     Type Delete(int &t, Type k) {
         sz[t]--;
         if ((key[t] == k) || (k < key[t] &&  == lch[t]) || (k > key[t] &&  == rch[t])) {
             Type tmp = key[t];
             if ( == lch[t] ||  == rch[t]) {
                 t = lch[t] + rch[t];
             } else {
                 key[t] = Delete(lch[t], key[t] + );
             }
             return tmp;
         } else {
             if (k < key[t]) {
                 return Delete(lch[t], k);
             } else {
                 return Delete(rch[t], k);
             }
         }
     }
 private:
     int root;
 };
 
 SBT <int> sbt[maxn<<];
 int a[maxn];
 
 void build(int L,int R,int o) {
     sbt[o].Clear();
     for(int i=L;i<=R;i++) {
         sbt[o].InsertR(a[i]);
     }
     if(L==R) return ;
     int mid=(L+R)>>;
     build(L,mid,o<<);
     build(mid+,R,o<<|);
 }
 void Update(int L,int R,int o,int pos,int val) {
     sbt[o].Delete(a[pos]);
     sbt[o].InsertR(val);
     if(L==R) return ;
     int mid=(L+R)>>;
     if(pos<=mid) Update(L,mid,o<<,pos,val);
     if(pos>mid) Update(mid+,R,o<<|,pos,val);
 }
 
 int Query(int L,int R,int o,int ls,int rs,int val) {
     if(ls<=L&&rs>=R) {
         return sbt[o].GetRank(val);
     }
     int mid=(L+R)>>; int res=;
     if(ls<=mid) res+=Query(L,mid,o<<,ls,rs,val);
     if(rs>mid) res+=Query(mid+,R,o<<|,ls,rs,val);
     return res;
 }
 inline int read()
 {
     int m=;
     char ch=getchar();
     while(ch<''||ch>''){ch=getchar(); }
     while(ch>=''&&ch<=''){m=m*+ch-''; ch=getchar(); }
     return m;
 }
 int main() {
     int n,m; char op[];
     int ls,rs,val;
     while(scanf("%d %d",&n,&m)==) {
         for(int i=;i<=n;i++) {
             a[i]=read();
         }
         SBT<int> :: ClearAll();
         build(,n,);
         for(int i=;i<=m;i++) {
             scanf("%s",op);
             if(op[]=='C') {
                 ls=read(); rs=read(); val=read();
                 int ans=Query(,n,,ls,rs,val);
                 printf("%d\n",ans);
             }
             else {
                 ls=read(); rs=read();
                 Update(,n,,ls,val);
                 a[ls]=val;
             }
         }
     }
     return ;

238 }

SPOJ 3261 (树套树傻逼题)的更多相关文章

  1. BZOJ4644: 经典傻逼题【线段树分治】【线性基】

    Description 这是一道经典傻逼题,对经典题很熟悉的人也不要激动,希望大家不要傻逼. 考虑一张N个点的带权无向图,点的编号为1到N. 对于图中的任意一个点集 (可以为空或者全集),所有恰好有一 ...

  2. BZOJ_3196_二逼平衡树_(树套树,线段树+Treap)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=3196 可以处理区间问题的平衡树. 3196: Tyvj 1730 二逼平衡树 Time Lim ...

  3. bzoj3196: Tyvj 1730 二逼平衡树 树套树

    地址:http://www.lydsy.com/JudgeOnline/problem.php?id=3196 题目: 3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec ...

  4. ZJOI2013 K大数查询 和 LG3380【模板】二逼平衡树(树套树)

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

  5. P3380 【模板】二逼平衡树(树套树)(线段树套平衡树)

    P3380 [模板]二逼平衡树(树套树) 前置芝士 P3369 [模板]普通平衡树 线段树套平衡树 这里写的是线段树+splay(不吸氧竟然卡过了) 对线段树的每个节点都维护一颗平衡树 每次把给定区间 ...

  6. 洛谷 P3380 bzoj3196 Tyvj1730 【模板】二逼平衡树(树套树)

    [模板]二逼平衡树(树套树) 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 查询k在区间内的排名 查询区间内排名为k的值 修改某一位值上的数值 查询k在 ...

  7. 洛谷P3380 【模板】二逼平衡树(树套树)(线段树+树状数组)

    P3380 [模板]二逼平衡树(树套树) 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 查询k在区间内的排名 查询区间内排名为k的值 修改某一位值上的数 ...

  8. [bzoj3196][Tyvj1730]二逼平衡树_树套树_位置线段树套非旋转Treap/树状数组套主席树/权值线段树套位置线段树

    二逼平衡树 bzoj-3196 Tyvj-1730 题目大意:请写出一个维护序列的数据结构支持:查询给定权值排名:查询区间k小值:单点修改:查询区间内定值前驱:查询区间内定值后继. 注释:$1\le ...

  9. 洛谷 P3380 【模板】二逼平衡树(树套树)-线段树套splay

    P3380 [模板]二逼平衡树(树套树) 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 查询k在区间内的排名 查询区间内排名为k的值 修改某一位值上的数 ...

  10. 「luogu3380」【模板】二逼平衡树(树套树)

    「luogu3380」[模板]二逼平衡树(树套树) 传送门 我写的树套树--线段树套平衡树. 线段树上的每一个节点都是一棵 \(\text{FHQ Treap}\) ,然后我们就可以根据平衡树的基本操 ...

随机推荐

  1. JDBC中Oracle的SID和ServiceName两种方式的连接字符串格式

    SID格式: jdbc:oracle:thin:@<host>:<port>:<SID> 如: jdbc:oracle:thin:@192.168.1.1:1521 ...

  2. Android中集成第三方支付

    常见的第三方支付解决方案 支付宝支付 微信支付 银联支付 Ping++统一支付平台(需要继承服务器端和客户端) 短信支付 支付宝的集成流程 相关资料链接: 支付宝支付指引流程:支付指引流程 支付宝An ...

  3. xUtils 简介

    ## xUtils简介* xUtils 包含了很多实用的android工具.* xUtils 最初源于Afinal框架,进行了大量重构,使得xUtils支持大文件上传,更全面的http请求协议支持(1 ...

  4. API系列一:REST和RESTful认识

    序言 最近工作的项目一直使用API,就想趁這个机会,把API的知识点进行一次梳理和总结,顺便提升一下自己对API全新的认识 Web API 是ASP.NET平台新加的一个特性,它可以简单快速地创建We ...

  5. JS中的Promise

    Promise 对象有以下两个特点. (1)对象的状态不受外界影响.Promise 对象代表一个异步操作,有三种状态:Pending(进行中).Resolved(已完成,又称 Fulfilled)和 ...

  6. Fragment懒加载预加载

    1. 预加载viewpager.setOffscreenPageLimit(2);,默认是预加载1,可以结合懒加载使用. 如果希望进入viewpager,Fragment只加载一次,再次滑动不需加载( ...

  7. 从Excel读取数据,然后分析相似的数据,多线程处理(多线程比较相似的字符串,统计出相似的数量及字符串)

    之前的jar包有问题,现已修改. 需要的jar包,已修改 自己去Maven中央仓库下载jar包. excel数据: 直接上代码. 程序再度优化了一遍.之后如果想再度精准,可能需要建模,最近没空继续做了 ...

  8. Spring Data Redis入门示例:基于Jedis及底层API (二)

    使用底层API:RedisConnectionFactory和RedisConnection可以直接操作Redis,下面是一个简单的例子: ### Maven依赖 <properties> ...

  9. RNN,LSTM,GRU基本原理的个人理解

    记录一下对RNN,LSTM,GRU基本原理(正向过程以及简单的反向过程)的个人理解 RNN Recurrent Neural Networks,循环神经网络 (注意区别于recursive neura ...

  10. Oracle存储过程和程序包

    一.为什么要用存储过程? 如果在应用程序中经常需要执行特定的操作,可以基于这些操作简历一个特定的过程.通过使用过程可以简化客户端程序的开发和维护,而且还能提高客户端程序的运行性能. 二.过程的优点? ...