[省选] [线段树] [BZOJ1012] JSOI2008 最大值 (max)
2016-04-26 19:07
585 查看
Description 题目描述
给定一列正整数al,a2,… ,an,每一个数都在0至p-1之间。可以对这列数进行两种操作:
添加操作:向序列后添加一个数,序列长度变成n+1。
询问操作:询问这个序列中最后L个数中最大的数是多少.
程序运行的最开始,整个序列为空。写一个程序,读入操作的序列,并输出询问操作的答案.
Input 输入
输入文件的第一行有两个正整数m(1≤m≤2*10^5)和p(1≤p≤2*10^9)。
接下来的m行,每行表示一个操作。
如果该行的内容是Q L,则表示这个操作是询问序列中最后L个数的最大数是多少;
如果是A t(0≤t≤p),则表示向序列后面加一个数,加入的数是:(t+a)除以p的余数。
其中,t是输入的参数,a是在这个添加操作之前最后一个询问操作的答案(如果之前没有询问操作,则a=0)。
第一个操作—定是添加操作。对于询问操作,L>0且不超过当前序列的长度。
Output 输出
对于每一个询问操作,输出一行。该行只有一个数,即序列中最后L个数的最大数
Sample Input 样例输入
10 100
A 97
Q 1
Q 1
A 17
Q 2
A 63
Q 1
Q 1
Q 3
A 99
Sample Output 样例输出
97
97
97
60
60
97
很明显,这道题是裸线段树,先建一棵空树,开一个计数器记下已经进入的个数,两个操作就可以抽象为:
(1)加入操作(eg:加入R) 改一下num位置的值为(R+last)%p
(2)查询操作(eg:查最后R个) 查一下[num-R+1,num)的最大值即可
其实是水题,并没有怎么卡(想要卡的?看看2015山东省选第二轮D1 音质检测……)
上代码……
线段树真是好东西……
数据可以在这里下载
给定一列正整数al,a2,… ,an,每一个数都在0至p-1之间。可以对这列数进行两种操作:
添加操作:向序列后添加一个数,序列长度变成n+1。
询问操作:询问这个序列中最后L个数中最大的数是多少.
程序运行的最开始,整个序列为空。写一个程序,读入操作的序列,并输出询问操作的答案.
Input 输入
输入文件的第一行有两个正整数m(1≤m≤2*10^5)和p(1≤p≤2*10^9)。
接下来的m行,每行表示一个操作。
如果该行的内容是Q L,则表示这个操作是询问序列中最后L个数的最大数是多少;
如果是A t(0≤t≤p),则表示向序列后面加一个数,加入的数是:(t+a)除以p的余数。
其中,t是输入的参数,a是在这个添加操作之前最后一个询问操作的答案(如果之前没有询问操作,则a=0)。
第一个操作—定是添加操作。对于询问操作,L>0且不超过当前序列的长度。
Output 输出
对于每一个询问操作,输出一行。该行只有一个数,即序列中最后L个数的最大数
Sample Input 样例输入
10 100
A 97
Q 1
Q 1
A 17
Q 2
A 63
Q 1
Q 1
Q 3
A 99
Sample Output 样例输出
97
97
97
60
60
97
很明显,这道题是裸线段树,先建一棵空树,开一个计数器记下已经进入的个数,两个操作就可以抽象为:
(1)加入操作(eg:加入R) 改一下num位置的值为(R+last)%p
(2)查询操作(eg:查最后R个) 查一下[num-R+1,num)的最大值即可
其实是水题,并没有怎么卡(想要卡的?看看2015山东省选第二轮D1 音质检测……)
上代码……
#include <cstdio> #define MAXN 800000//开的好像有点大,不过也没事了^_^ using namespace std; struct rec { int p,r,m; int left,right; int sum; }; int m,p,top=1; int num,last;//num为计数器,last为“上一次操作”的最后一个数 rec tree[2*MAXN]={}; char flag[3]; int n; int mymax(int a,int b) { return a>b?a:b; } //以下为正常的线段树代码...... //代码区间为左闭右开,注意,注意 void Build_A_Tree(int u) { if (tree[u].p+1==tree[u].r) return; tree[u].m=(tree[u].p+tree[u].r)/2; top++; tree[u].left=top; tree[top].p=tree[u].p; tree[top].r=tree[u].m; Build_A_Tree(top); top++; tree[u].right=top; tree[top].p=tree[u].m; tree[top].r=tree[u].r; Build_A_Tree(top); } //在看之前,请默念左闭右开 void modify (int u,int x,int v) { if ((tree[u].p+1==tree[u].r)) { tree[u].sum=v; return; } if (x<tree[u].m) modify(tree[u].left,x,v); else modify(tree[u].right,x,v); tree[u].sum=mymax(tree[tree[u].left].sum,tree[tree[u].right].sum); } //左闭右开 int query (int u,int a,int b) { if ((tree[u].p==a)&&(tree[u].r==b)) return tree[u].sum; if (tree[u].m>=b) return query(tree[u].left,a,b); else if (tree[u].m<=a) return query(tree[u].right,a,b); else return mymax(query(tree[u].left,a,tree[u].m),query(tree[u].right,tree[u].m,b)); } int main() { //freopen("data.in","r",stdin);freopen("data.out","w",stdout); scanf("%d %d",&m,&p); tree[1].p=1; tree[1].r=m+1;//显然树的最大容量为m Build_A_Tree(1); while (m--) { scanf("%s",flag);//我讨厌输入字符...... scanf("%d",&n); if (flag[0]=='A')//这里是加入操作 { num++; n=(n+last)%p;//按题目要求写 modify(1,num,n); } else//这里是查询操作 { last=query(1,num-n+1,num+1); printf("%d\n",last); } } return 0; }
线段树真是好东西……
数据可以在这里下载
相关文章推荐
- Javascript 使用Hashmap/Dict 和陷阱
- url的三个js编码函数escape(),encodeURI(),encodeURIComponent()简介
- javascript浏览器参数的操作,js获取浏览器参数
- js时间戳转日期格式
- json.dumps loads 终于区分出来了
- SCRIPT5039: 重新声明常量属性 遇到js错误,在IE9下会调试脚本会出现
- Extjs GridPanel用法详解
- JSTL标签变量Map集合
- javascript中this
- extjs中treepanel属性和方法
- JavaScript 进阶学习 2 数组
- JavaScript 进阶学习 1
- js window resize延时
- 任意角度的矩形与圆形的碰撞检测
- JS 正则表达式初体验
- js清除浏览器缓存的几种方法
- Jsduck
- js 实现自动调出键盘
- 使用JavaScript实现数组去重的几种方式
- js里面“===”与“==”的区别