Problem H:Boring Counting

Time Limit : 6000/3000ms (Java/Other)   Memory Limit : 65535/32768K (Java/Other)

Problem Description

In this problem you are given a number sequence P consisting of N integer and Pi is the ith element in the sequence. Now you task is to answer a list of queries, for each query, please tell us among [L, R], how many Pi is not less than A and not greater than B( L<= i <= R). In other words, your task is to count the number of Pi (L <= i <= R,  A <= Pi <= B).

Input

In the first line there is an integer T (1 < T <= 50), indicates the number of test cases.
        For each case, the first line
contains two numbers N and M (1 <= N, M <= 50000), the size of sequence
P, the number of queries. The second line contains N numbers Pi(1
<= Pi <= 10^9), the number sequence P. Then there are M lines,
each line contains four number L, R, A, B(1 <= L, R <= n, 1 <= A, B
<= 10^9)

Output

For each case, at first output a line
‘Case #c:’, c is the case number start from 1. Then for each query output a
line contains the answer.

Sample Input

1

13
5

6
9 5 2 3 6 8 7 3 2 5 1 4

1
13 1 10

1
13 3 6

3
6 3 6

2
8 2 8

1
9 1 9

Sample Output

Case
#1:

13

7

3

6

9

给你n个数和m条询问,每次查询区间[l,r]中满足A<=x<=B的x的个数。

感觉很不错的一道题,考察主席树的应用。

关于主席树,请参考:http://seter.is-programmer.com/posts/31907.html

建立n棵线段树,线段树root[i]代表区间[1,i]之间一段数字区间出现的次数。

对于每一棵线段树,每个节点表示一个区间[a,b],记录满足a<=x<=b的x的个数。

因为线段树root[i]是在线段树root[i-1]的基础上增加了一个数得到的,所以可以由root[i-1]得到root[i]。

由于每棵线段树的大小形态都是一样的,而且初始值全都是0,那每个线段树都初始化不是太浪费了?所以一开始只要建一棵空树即可。

然后是在某棵树上修改一个数字,由于和其他树相关联,所以不能在原来的树上改,必须弄个新的出来。难道要弄一棵新树?不是的,由于一个数字的更改只影响了一条从这个叶子节点到根的路径,所以只要只有这条路径是新的,另外都没有改变。比如对于某个节点,要往右边走,那么左边那些就不用新建,只要用个指针链到原树的此节点左边就可以了,这个步骤的前提也是线段树的形态一样。

n是数字个数,这个步骤的空间复杂度显然是O(logn)。

所有树节点的空间消耗为:O(n*4+nlogn)

预处理得到所有的root[i]。

查询时在两棵线段树root[R]和root[L-1]中分别查询区间[A,B]中数的个数,相减即是结果。

本题的时间复杂度:建树:O(n)+预处理O(nlogn)+查询O(logn)

 #include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm> using namespace std; #define lson l, m, rt->left
#define rson m + 1, r, rt->right const int MAXN = ;
const int INF = (1e9)+; struct Node
{
int sum; //存储区间[A, B]之间一共有多少个数
Node *left, *right;
}; Node *root[MAXN];
Node ChairTree[ MAXN * ];
Node *idx; int pos[MAXN]; //处于位置i的数排第几
int num[MAXN]; //排好序并去重的原始数,相当于把所有数离散化之后的结果
int p[MAXN]; //排第i的是哪个数
int cnt, n, Q; bool cmp( int a, int b )
{
return pos[a] < pos[b];
} Node *nextNode()
{
idx->sum = ;
idx->left = idx->right = NULL;
return idx++;
} Node *copyNode( Node *ori )
{
idx->sum = ori->sum;
idx->left = ori->left;
idx->right = ori->right;
return idx++;
} void PushUp( Node *rt )
{
rt->sum = rt->left->sum + rt->right->sum;
return;
} void build( int l, int r, Node* rt ) //建立一个空树
{
if ( l == r ) return; int m = ( l + r ) >> ; rt->left = nextNode();
rt->right = nextNode(); build( lson );
build( rson ); return;
} void init()
{
scanf( "%d%d", &n, &Q ); for ( int i = ; i <= n; ++i )
{
scanf( "%d", &pos[i] );
p[i] = i;
}
sort( p + , p + + n, cmp ); int pre = -INF;
cnt = ;
for ( int i = ; i <= n; ++i ) //离散化+去重
{
if ( pos[ p[i] ] == pre )
pos[ p[i] ] = cnt;
else
{
pre = pos[ p[i] ];
num[ ++cnt ] = pos[ p[i] ];
pos[ p[i] ] = cnt;
}
}
return;
} Node *add( int val, int l, int r, Node* rt ) //根据上一棵树构造下一棵树
{
Node *temp = copyNode( rt ); if ( l == r )
{
temp->sum += ;
return temp;
}
int m = ( l + r ) >> ;
if ( val <= m ) temp->left = add( val, lson );
else temp->right = add( val, rson );
PushUp( temp ); return temp;
} int Query( int L, int R, int l, int r, Node* treeL, Node* treeR )
{
if ( L <= l && r <= R )
{
return treeR->sum - treeL->sum;
}
int res = ; int m = ( l + r ) >> ;
if ( L <= m ) res += Query( L, R, l, m, treeL->left, treeR->left );
if ( R > m ) res += Query( L, R, m + , r, treeL->right, treeR->right );
return res;
} void chuli()
{
idx = ChairTree;
root[] = nextNode();
build( , cnt, root[] ); //建立一颗空树 for ( int i = ; i <= n; ++i )
root[i] = add( pos[i], , cnt, root[i - ] ); //根据第i-1棵树构造第i棵树
return;
} int BiSearch1( int tar ) //查询最左边的 >= x 的数
{
int low = , high = cnt;
int mid, ans = -;
while ( low <= high )
{
mid = ( low + high ) >> ;
if ( num[mid] >= tar )
{
ans = mid;
high = mid - ;
}
else low = mid + ;
}
return ans;
} int BiSearch2( int tar ) //查询最右边的 <= x 的数
{
int low = , high = cnt;
int mid, ans = -;
while ( low <= high )
{
mid = ( low + high ) >> ;
if ( num[mid] <= tar )
{
ans = mid;
low = mid + ;
}
else high = mid - ;
}
return ans;
} int main()
{
int T, cas = ;
scanf( "%d", &T );
while ( T-- )
{
init();
chuli(); printf( "Case #%d:\n", ++cas );
while ( Q-- )
{
int l, r, a, b;
scanf("%d%d%d%d", &l, &r, &a, &b );
int u = BiSearch1( a );
int v = BiSearch2( b );
if ( u == - || v == - )
{
puts("");
continue;
}
printf( "%d\n", Query( u, v, , cnt, root[l - ], root[r] ) );
}
}
return ;
}

UPC 2224 / “浪潮杯”山东省第四届ACM大学生程序设计竞赛 1008 Boring Counting 主席树的更多相关文章

  1. “浪潮杯”山东省第五届ACM大学生程序设计竞赛(总结贴)

    第一次參加省赛有点小激动,尽管是作为打星队參赛,但心情却是上下起伏. 5月9号晚上11点多到威海,有点略冷.可是空气比淄博好多了,大家到了旅馆的时候都非常晚了,抱怨了一下三星级的酒店的待遇,喝杯咖啡早 ...

  2. 2012年"浪潮杯"山东省第三届ACM大学生程序设计竞赛--n a^o7 ! 分类: 比赛 2015-06-09 17:16 14人阅读 评论(0) 收藏

    n a^o7 ! Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 All brave and intelligent fighte ...

  3. 山东省第四届ACM大学生程序设计竞赛解题报告(部分)

    2013年"浪潮杯"山东省第四届ACM大学生程序设计竞赛排名:http://acm.upc.edu.cn/ranklist/ 一.第J题坑爹大水题,模拟一下就行了 J:Contes ...

  4. Alice and Bob(2013年山东省第四届ACM大学生程序设计竞赛)

    Alice and Bob Time Limit: 1000ms   Memory limit: 65536K 题目描述 Alice and Bob like playing games very m ...

  5. 2013年山东省第四届ACM大学生程序设计竞赛-最后一道大水题:Contest Print Server

    点击打开链接 2226: Contest Print Server Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 53  Solved: 18 [Su ...

  6. sdut Mountain Subsequences 2013年山东省第四届ACM大学生程序设计竞赛

    Mountain Subsequences 题目描述 Coco is a beautiful ACMer girl living in a very beautiful mountain. There ...

  7. 2013年山东省第四届ACM大学生程序设计竞赛J题:Contest Print Server

    题目描述     In ACM/ICPC on-site contests ,3 students share 1 computer,so you can print your source code ...

  8. 2013年山东省第四届ACM大学生程序设计竞赛 Alice and Bob

      Alice and Bob Time Limit: 1000ms   Memory limit: 65536K 题目描述 Alice and Bob like playing games very ...

  9. 2013年山东省第四届ACM大学生程序设计竞赛E题:Alice and Bob

    题目描述 Alice and Bob like playing games very much.Today, they introduce a new game. There is a polynom ...

随机推荐

  1. HDU 2669 第六周 I题

    Description The Sky is Sprite.  The Birds is Fly in the Sky.  The Wind is Wonderful.  Blew Throw the ...

  2. 无法创建链接服务器 "TEST" 的 OLE DB 访问接口 "OraOLEDB.Oracle" 的实例

    在使用SQLserver建立远程服务连接Oracle的时候出现先下面错误 出现这个错误,我找到最常见的两个原因 1.注册表 <1>按下WIN+R,打开“运行”窗口,输入“regedit”, ...

  3. Kill 所有MySQL进程

    如果在单机上安装了N多mysql数据库单实例,不再使用的情况下,想关闭所有进程,方法很简单的了,哈哈哈. kill -9 `ps -ef|grep DataServer|awk '{print $2} ...

  4. oracle 子查询因子化 浅谈(with的使用)

    近来学习oracle,想要提高自己所写语句的效率和易读性,今天的笔记是关于子查询因子话这么一个东西 因子化的查询不一定可以提高效率,但是一定可以再提高程序的可读性方面成效显著 --with 语句 wi ...

  5. [转]adb pull Permission denied及no such file错误

    adb pull  Permission denied及no such file错误 http://www.the8m.com/blog/article/javadk/adbpull.html XP系 ...

  6. cocos2dx中的触摸事件及触摸优先级

    1.只有CCLayer及其派生类才有触摸功能. 2.开启触摸 setTouchEnable(true); 3.设置触摸模式,单点,多点(仅IOS支持) setTouchMode(kCCTouchesO ...

  7. 获取不到app.config里面的数据库连接字符串的解决方法

    今天在自己的类库里添加了对app.config文件的数据库连接字符串的引用,但是返回的居然是Null,纳闷了.然后在网上找到了答案原来是我的app.config文件加错了地方,应该加到启动项目里面,而 ...

  8. 自己的一些 Demo,源码链接

    1.指纹解锁(GitHub). 2.JS 与 OC 交互(GitHub). 3.模仿 HTML 下拉菜单(GitHub). 4.OC开发常用类目(GitHub).

  9. Python标准库之os模块

    1.删除和重命名文件 import os import string def replace(file, search_for, replace_with): # replace strings in ...

  10. 2007: [Noi2010]海拔 - BZOJ

    Description YT市是一个规划良好的城市,城市被东西向和南北向的主干道划分为n×n个区域.简单起见,可以将YT市看作一个正方形,每一个区域也可看作一个正方形.从而,YT城市中包括(n+1)× ...