HUST 1407(数据结构)

1407 - 郁闷的小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

……

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

INPUT

第一行两个整数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的正数。)

OUTPUT

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



sl: 首先随便写了个 线段树套set的方法,不出预料的TLE .

然后又写了个线段树套SBT的写法  ,不能忍的TIE.

最后托人写了个二进制trie的方法  ,AC。但是本若菜不想写虽然很短。

继续yy,  发现用map 吧相同的数字的位置维护一下,这个可以用sbt,或是任何的数据结构都可以吧。然后就能过了。但是不想敲了,囧。

先贴上几份sb了的代码。AC代码随后补上。

正确代码可以参考:   http://vjudge.net/vjudge/problem/viewSource.action?id=2690221   (我就不贴了。。)

我的两份 :

1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <vector>
  5 #include <set>
  6 using namespace std;
  7 const int MAX = 100000+10;
  8 int a[MAX];
  9 
 10 struct Node {
 11     int key, val;
 12     Node(){};
 13     Node(int a, int b) { key = a; val = b; }
 14     bool operator < (Node b)  { return val < b.val; }
 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     Node operator + (int a) {
 20         return Node(key, val+a) > Node(key, val) ? Node(key, val+a) : Node(key, val-a);
 21     }
 22 };
 23 
 24 int sz[MAX*30];
 25 int key[MAX*30];
 26 int lch[MAX*30];
 27 int rch[MAX*30];
 28 int tot;
 29 
 30 template<typename Type>
 31 class SBT
 32 {
 33 public:
 34     SBT() { Clear(); }
 35     void Clear() { root = 0; lch[0] = rch[0] = sz[0] = 0; }
 36     static void ClearAll() { tot = 0; }
 37     int Size() { return sz[root]; }
 38     bool Empty() { return 0 == sz[root]; }
 39     bool Find(Type k) { return Find(root, k); }
 40     void InsertR(Type k) { Insert(root, k); } // 可重复插入
 41     void Insert(Type k) { if (!Find(k)) Insert(root, k); }
 42     void Delete(Type k) { if (Find(k)) Delete(root, k); }
 43     void DeleteSmaller(Type k) { DeleteSmaller(root, k); }
 44     int GetRank(Type k) { return GetRank(root, k); }
 45     Type GetKth(int k) { return GetKth(root, k); }
 46     Type GetMin() { return GetKth(root, 1); }
 47     Type GetMax() { return GetKth(root, Size()); }
 48     Type GetPre(Type k) { return GetPre(root, k); }
 49     Type GetSuc(Type k) { return GetSuc(root, k); }
 50     int GetSmaller(Type k) { return GetSmaller(root, k); } // 返回小于k的元素的个数
 51 
 52 private:
 53     void LeftRotate(int &t) {
 54         int k = rch[t];
 55         rch[t] = lch[k];
 56         lch[k] = t;
 57         sz[k] = sz[t];
 58         sz[t] = 1 + sz[lch[t]] + sz[rch[t]];
 59         t = k;
 60     }
 61     void RightRotate(int &t) {
 62         int k = lch[t];
 63         lch[t] = rch[k];
 64         rch[k] = t;
 65         sz[k] = sz[t];
 66         sz[t] = 1 + sz[lch[t]] + sz[rch[t]];
 67         t = k;
 68     }
 69     void Maintain(int &t, bool flag) {
 70         if (0 == t) return ;
 71         if (false == flag) {
 72             if (sz[lch[lch[t]]] > sz[rch[t]]) {
 73                 RightRotate(t);
 74             } else if (sz[rch[lch[t]]] > sz[rch[t]]) {
 75                 LeftRotate(lch[t]);
 76                 RightRotate(t);
 77             } else {
 78                 return ;
 79             }
 80         } else {
 81             if (sz[rch[rch[t]]] > sz[lch[t]]) {
 82                 LeftRotate(t);
 83             } else if (sz[lch[rch[t]]] > sz[lch[t]]) {
 84                 RightRotate(rch[t]);
 85                 LeftRotate(t);
 86             } else {
 87                 return ;
 88             }
 89         }
 90         Maintain(lch[t], false);
 91         Maintain(rch[t], true);
 92         Maintain(t, false);
 93         Maintain(t, true);
 94     }
 95     Type GetPre(int t, Type k) {
 96         if (0 == k) return k;
 97         if (k <= key[t]) return GetPre(lch[t], k);
 98         Type tmp = GetPre(rch[t], k);
 99         if (tmp == k) return key[t];
100         return tmp;
101     }
102     Type GetSuc(int t, Type k) {
103         if (0 == root) return k;
104         if (k >= key[t]) return GetSuc(rch[t], k);
105         Type tmp = GetSuc(lch[t], k);
106         if (tmp == k) return key[t];
107         return tmp;
108     }
109     Type GetKth(int t, int k) {
110         if (sz[lch[t]] >= k) return GetKth(lch[t], k);
111         if (sz[lch[t]] == k - 1) return key[t];
112         return GetKth(rch[t], k - sz[lch[t]] - 1);
113     }
114     int GetRank(int t, Type k) {
115         if (0 == t) return 0;
116         if (k < key[t]) return GetRank(lch[t], k);
117         return sz[lch[t]] + 1 + GetRank(rch[t], k);
118     }
119     int GetSmaller(int t, Type k) {
120         if (0 == t) return 0;
121         if (k <= key[t]) return GetSmaller(lch[t], k);
122         return sz[lch[t]] + 1 + GetSmaller(rch[t], k);
123     }
124     bool Find(int t, Type k) {
125         if (0 == t) return false;
126         else if (k < key[t]) return Find(lch[t], k);
127         else return (key[t] == k || Find(rch[t], k));
128     }
129     void Insert(int &t, Type k) {
130         if (0 == t) {
131             t = ++tot;
132             lch[t] = rch[t] = 0;
133             sz[t]= 1;
134             key[t] = k;
135             return ;
136         }
137         sz[t]++;
138         if (k < key[t]) Insert(lch[t], k);
139         else Insert(rch[t], k);
140         Maintain(t, k >= key[t]);
141     }
142     void DeleteSmaller(int &t , Type k) {
143         if (0 == t) return ;
144         if ( key[t] < k ) {
145             t = rch[t];
146             DeleteSmaller(t , key);
147         } else {
148             DeleteSmaller(lch[t] , k);
149             sz[t] = 1 + sz[lch[t]] + sz[rch[t]];
150         }
151     }
152     Type Delete(int &t, Type k) {
153         sz[t]--;
154         if ((key[t] == k) || (k < key[t] && 0 == lch[t]) || (k > key[t] && 0 == rch[t])) {
155             Type tmp = key[t];
156             if (0 == lch[t] || 0 == rch[t]) {
157                 t = lch[t] + rch[t];
158             } else {
159                 key[t] = Delete(lch[t], key[t] + 1);
160             }
161             return tmp;
162         } else {
163             if (k < key[t]) {
164                 return Delete(lch[t], k);
165             } else {
166                 return Delete(rch[t], k);
167             }
168         }
169     }
170 private:
171     int root;
172 };
173 
174 SBT<int> sbt[MAX<<2];
175 inline int read()
176 {
177     int m=0;
178     char ch=getchar();
179     while(ch<‘0‘||ch>‘9‘){ch=getchar(); }
180     while(ch>=‘0‘&&ch<=‘9‘){m=m*10+ch-‘0‘; ch=getchar(); }
181     return m;
182 }
183 void build(int L,int R,int o) {
184     //sbt[o].Clear();
185     for(int i=L;i<=R;i++) {
186         sbt[o].InsertR(a[i]);
187     }
188     if(L==R) return;
189     int mid=(L+R)>>1;
190     build(L,mid,o<<1);
191     build(mid+1,R,o<<1|1);
192 }
193 void Update(int L,int R,int o,int pos,int val) {
194     sbt[o].Delete(a[pos]);
195     sbt[o].InsertR(val);
196     if(L==R) return ;
197     int mid=(L+R)>>1;
198     if(pos<=mid) Update(L,mid,o<<1,pos,val);
199     else Update(mid+1,R,o<<1|1,pos,val);
200 }
201 int Query(int L,int R,int o,int ls,int rs,int val) {
202     if(ls<=L&&rs>=R) {
203         int ans=sbt[o].GetRank(val)-sbt[o].GetRank(val-1);
204         return ans;
205     }
206     int mid=(L+R)>>1;
207     int res=0;
208     if(ls<=mid) res+=Query(L,mid,o<<1,ls,rs,val);
209     if(rs>mid) res+=Query(mid+1,R,o<<1|1,ls,rs,val);
210     return res;
211 }
212 
213 int main() {
214     int n,m; char op[10];
215     int ls,rs,val;
216     while(scanf("%d %d",&n,&m)==2) {
217         for(int i=1;i<=n;i++) {
218             a[i]=read();
219         }
220 
221         build(1,n,1);
222         for(int i=1;i<=m;i++) {
223             scanf("%s",op);
224             if(op[0]==‘Q‘) {
225                 ls=read(); rs=read(); val=read();
226                 int ans=Query(1,n,1,ls,rs,val);
227                 printf("%d\n",ans);
228             }
229             else {
230                 ls=read(); val=read();
231                 Update(1,n,1,ls,val);
232                 a[ls]=val;
233             }
234         }
235     }
236     return 0;
237 }

1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <vector>
 5 #include <set>
 6 using namespace std;
 7 const int MAX = 100000+10;
 8 multiset<int> hash[MAX<<2];
 9 int a[MAX];
10 inline int read()
11 {
12     int m=0;
13     char ch=getchar();
14     while(ch<‘0‘||ch>‘9‘){ch=getchar(); }
15     while(ch>=‘0‘&&ch<=‘9‘){m=m*10+ch-‘0‘; ch=getchar(); }
16     return m;
17 }
18 void build(int L,int R,int o) {
19     hash[o].clear();
20     for(int i=L;i<=R;i++) {
21         hash[o].insert(a[i]);
22     }
23 
24     if(L==R) return ;
25     int mid=(L+R)>>1;
26     build(L,mid,o<<1);
27     build(mid+1,R,o<<1|1);
28 }
29 void Update(int L,int R,int o,int pos,int val) {
30     hash[o].erase(hash[o].find(a[pos]));
31     hash[o].insert(val);
32     if(L==R) return ;
33     int mid=(L+R)>>1;
34     if(pos<=mid) Update(L,mid,o<<1,pos,val);
35     else Update(mid+1,R,o<<1|1,pos,val);
36 }
37 int Query(int L,int R,int o,int ls,int rs,int val) {
38     if(ls<=L&&rs>=R) {
39         return hash[o].count(val);
40     }
41     int mid=(L+R)>>1;
42     int res=0;
43     if(ls<=mid) res+=Query(L,mid,o<<1,ls,rs,val);
44     if(rs>mid) res+=Query(mid+1,R,o<<1|1,ls,rs,val);
45     return res;
46 }
47 
48 int main() {
49     int n,m; char op[10];
50     int ls,rs,val;
51     scanf("%d %d",&n,&m);
52     for(int i=1;i<=n;i++) {
53         a[i]=read();
54     }
55 
56     build(1,n,1);
57     for(int i=1;i<=m;i++) {
58         scanf("%s",op);
59         if(op[0]==‘Q‘) {
60             ls=read(); rs=read(); val=read();
61             int ans=Query(1,n,1,ls,rs,val);
62             printf("%d\n",ans);
63         }
64         else {
65             ls=read(); val=read();
66             Update(1,n,1,ls,val);
67             a[ls]=val;
68         }
69     }
70 
71     return 0;
72 }

HUST 1407(数据结构),布布扣,bubuko.com

时间: 2024-10-18 12:20:07

HUST 1407(数据结构)的相关文章

3.1 基础数据结构回顾

例题1  uva11995  http://acm.hust.edu.cn/vjudge/problem/18700 猜测符合哪种数据结构 , 用stl模拟判断. 1 //#define txtout 2 //#define debug 3 #include<bits/stdc++.h> 4 #define mt(a,b) memset(a,b,sizeof(a)) 5 using namespace std; 6 typedef long long LL; 7 const double pi

数据结构录 之 链表&amp;栈&amp;队列

三种基本的数据结构,来稍微说一下. 首先链表,这个几乎每本C++的语言书都会说的,直接看书上说的就好. 链表就是一个链,每一个都有一个指针指向下一个,然后这样串了起来.然后可以从头开始找,一直找到尾巴.然后对于某个数据点,都可以删除,只需要让他前面那个指向他后面那个,这样从头开始找的时候就找不到这个点了...在这个点之后添加一个点也是这样,直接让这个点指向那个新的,然后让新的指向原来这个点指向的后一个... 可以想象就是一个个点,然后第一个指向第二个,第二个指向第三个...就像是一条长长的链一样

数据结构与算法分析-排序

作者:xiabodan 出处:http://blog.csdn.net/xiabodan 排序算法(Sorting Algorithm)是计算机算法的一个组成部分.也是程序=算法+数据结构中的一部分(算法). 实验平台:raspberry 2 B + Ubuntu Mate 插入排序 外循环i由1到N-1,内循环由j由i到1,每次内循环都将A[j]插入到序列A[0]-A[i]的正确位置,这样就保证了每次外循环之后序列A[0]-A[i]都是已经排好序的,外循环不过将自己插入在A[0]-A[i]之间

AT&amp;T汇编语言与GCC内嵌汇编,Linux内核数据结构之链表

最近在看<Linux内核源代码情景分析>,作者毛德操.书中刚开始介绍了AT&T汇编语言与GCC内嵌汇编,以及Linux内核数据结构之链表.可惜书中介绍的不够全面.因为推荐大家阅读下面两篇文章.很不错. AT&T汇编语言与GCC内嵌汇编:http://grid.hust.edu.cn/zyshao/Teaching_Material/OSEngineering/Chapter2.pdf. Linux内核数据结构之链表:http://www.cnblogs.com/Anker/p/

【数据结构】之散列链表(Java语言描述)

散列链表,在JDK中的API实现是 HashMap 类. 为什么HashMap被称为"散列链表"?这与HashMap的内部存储结构有关.下面将根据源码进行分析. 首先要说的是,HashMap中维护着的是一个数组: transient Node<K,V>[] table; ,数组中的每个元素都是一个 Node 对象.这里的Node是HashMap的一个内部类,代码如下: static class Node<K,V> implements Map.Entry<

旧题新做:从idy的视角看数据结构

“今天你不写总结……!!!” 额…… 还是讲我的吧.这些考试都是idy出的题. 20170121:DFS序. ST表.线段树练习 这是第一次考数据结构. Problem 1. setsum 1 second 给你一个长度为N 的整数序列,支持两种操作: • modity l r val 将区间[l,r] 中的所有数修改为val • query l r 询问区间[l,r] 所有数的和 分析:最简单的线段树,区间更改区间求和.但注意是更改,不是添改,sum与flag需同时覆盖. Problem 2.

数据结构Set和Map

一.数据结构 Set 集合的基本概念:集合是由一组无序且唯一(即不能重复)的项组成的.这个数据结构使用了与有限集合相同的数学概念,应用在计算机的数据结构中.  特点:key 和 value 相同,没有重复的 value.ES6 提供了数据结构 Set.它类似于数组,但是成员的值都是唯一的,没有重复的值. 1. 如何创建一个 Set const s = new Set([1, 2, 3]); 2.属性 console.log(s.size); // 3 3.Set 类的方法 --set.add(v

数据结构基本概念

什么是数据结构 "数据结构是数据对象,以及存在于该对象的实例和组成实例的数据元素之间的各种联系.这些联系可以通过定义相关的函数来给出"--Sartaj Sahni,<数据结构.算法与应用> "数据结构是ADT(抽象数据类型Abstract Data Type)的物理实现."--Clifford A.Shaffer,<数据结构与算法分析> "数据结构(data structture)是计算机中存储.组织数据的方式.通常情况下,经i想你

分布式缓存技术redis学习系列(二)——详细讲解redis数据结构(内存模型)以及常用命令

Redis数据类型 与Memcached仅支持简单的key-value结构的数据记录不同,Redis支持的数据类型要丰富得多,常用的数据类型主要有五种:String.List.Hash.Set和Sorted Set. Redis数据类型内存结构分析 Redis内部使用一个redisObject对象来表示所有的key和value.redisObject主要的信息包括数据类型(type).编码方式(encoding).数据指针(ptr).虚拟内存(vm)等.type代表一个value对象具体是何种数