1540-线段树区间合并操作
来源:互联网 发布:2002数据库怎么使用 编辑:程序博客网 时间:2024/05/20 14:15
#include<stdio.h>#include<iostream>#include<stack>#include<cstring>using namespace std;const int MAX=1000000;struct pr { int lsum,rsum,msum; int left,right; }tr[MAX+10];int n,m;inline int ll(int k) {return 2*k;} inline int rr(int k) {return 2*k+1;} inline int mid(int kk1,int kk2) {return (kk1+kk2)>>1;}void pushup(int k){//m=r-l+1; int l=tr[k].left,r=tr[k].right; int mi=mid(l,r); tr[k].lsum =tr[ll(k)].lsum; tr[k].rsum =tr[rr(k)].rsum; if (tr[k].lsum == mi-l+1) tr[k].lsum+=tr[rr(k)].lsum; if (tr[k].rsum == r-mi) tr[k].rsum+=tr[ll(k)].rsum; tr[k].msum = max(tr[rr(k)].lsum+tr[ll(k)].rsum,max(tr[ll(k)].msum,tr[rr(k)].msum)); return;}void build(int k,int s,int t) { tr[k].left=s;tr[k].right=t; if(s==t) {tr[k].rsum=tr[k].lsum=tr[k].msum=1;return;} build(ll(k),s,mid(s,t)); build(rr(k),mid(s,t)+1,t); pushup(k); //pushup}void modify(int k,int in,int x) { int l=tr[k].left,r=tr[k].right; if(l==r) { if(x==1) tr[k].lsum=tr[k].msum=tr[k].rsum=0; else tr[k].lsum=tr[k].msum=tr[k].rsum=1; return ; } int mi=mid(l,r); if(in<=mi) modify(ll(k),in,x); else if(in>mi) modify(rr(k),in,x); pushup(k);}int query(int k,int x) { int l=tr[k].left,r=tr[k].right; if(l==r||tr[k].msum==0||tr[k].msum==r-l+1) return tr[k].msum; int mi=mid(l,r); int res=0; if (x<=mi){ if(tr[ll(k)].right-tr[ll(k)].rsum+1<=x) res=query(ll(k),x)+query(rr(k),mi+1); else res=query(ll(k),x); } else if(x>mi){ if(tr[rr(k)].lsum+tr[rr(k)].left-1>=x) res=query(rr(k),x)+query(ll(k),mi); else res=query(rr(k),x); } return res;}int main(){ while(cin>>n>>m){ build(1,1,n); char s[10]; int x; stack<int> Q; for(int i=0;i<m;i++){ scanf("%s",s); if(s[0]=='D'){ scanf("%d",&x); Q.push(x); modify(1,x,1); } else if(s[0]=='Q'){ scanf("%d",&x); printf("%d\n",query(1,x)); } else{ int y=Q.top(); Q.pop(); modify(1,y,0); } } } return 0;}
这是一道基础的线段树合并基本操作。
题意就是单点修改,然后查询单点所在的连续合法区间,初始化都是合法的。
这题的考点应该就是查询部分。
查询部分单独拿出来说一下,
if (x<=mi){ if(tr[ll(k)].right-tr[ll(k)].rsum+1<=x) res=query(ll(k),x)+query(rr(k),mi+1); else res=query(ll(k),x); }就拿查询点在mid的左来举个栗子,考虑到在左面如果只查询左区间很可能得到错误答案(例如x在rsum里那么q(x)的答案就会漏掉r右边的部分),所以在另一个区间查他的左端点就可以啦,所以这题大致就是这样的了。。其他类比就行了。。
蒟蒻写的搓大家见谅。。。继续努力。。鲤鱼王加油!
0 0
- 1540-线段树区间合并操作
- hdu3911线段树区间合并操作
- 【POJ 3667】 hotel 【线段树 +区间操作+区间合并】
- 线段树 区间合并
- 线段树 区间合并
- 线段树 区间合并
- 线段树 区间合并
- 线段树-区间合并
- hdu 1540 线段树区间合并
- hdu 1540 线段树+区间合并
- hdu 1540 线段树区间合并
- 线段树--区间合并--HDU 1540
- HDU 1540 线段树区间合并
- hdu 1540 线段树(区间合并入门)
- 线段树--区间合并hdu--1540
- POJ 3667 Hotel 带区间合并操作的线段树
- HDU 3911 线段树区间合并+异或操作
- bzoj1858:序列操作 (线段树区间信息合并)
- Android的性能优化
- memcache
- 腾讯笔试:>格雷码
- Navicat for Oracle如何连接数据库
- android 获取 imei号码及手机硬件其他信息
- 1540-线段树区间合并操作
- 七月算法机器学习笔记5 回归模型
- Android USB Host的使用详解
- ImageView.ScaleType设置图解
- iOS中assign,copy,retain之间的区别以及weak和strong的区别
- 单例模式
- mq
- Errors running builder 'DeploymentBuilder' on project_java
- Android 什么时候用Application的Context,什么时候用Activity的Context