题意:n次操作
操作1给区间【a,b】加上1
操作2查询某个点x的值
。。。。这不就是线段树的区间更新单点操作嘛。。。。。然后1<=a,b<= 10^9...也就是不能线段树直接来了
思路: 把每次输入的l 存到一个有序集合,每次输入的r存到一个有序集合
然后对于每次查询的点X。我们只需要看大于该点X的l有多少个,大于等于该点X的r有多少个,然后用r的个数减去l的个数。
就得到该点被覆盖的次数了...也就是该点的值
实现:
1、每次插入完,储存数据的结构必须是有序的(这里我用set.logn..)
2、每次查询的时候,用二分在有序结构中分别找到大于x的l和r (二分logn)
3、对于得到的大于X的l,和r, 还得知道他们在该有序结构中的排名...才能用总数-排名得到 大于X的个数...这里我用treap logn查询某个数的排名
复杂度就是 (n*logn)..
然而其实对 步骤 1 2 3其实直接用一个平衡树或者伸展树实现就好了....我等渣渣只好用set+treap狡猾地实现了。。。
代码在最后
----------------------------------------------------------------------------
另外一种做法是离线做法,对 点离散化 (比第一种稍快)
先把所有的操作输入储存,把所有查询的点 先离散化 排好序,(nlogn)
然后开始按输入顺序 执行
操作1: 每次给区间 【a,b】加1的时候,先在 <离散化+排序好的> 查询点 的数组中二分找到 第一个大于等于a的下标X和第一个大于b的下标Y 然后用树状数组 给 【x,y】加1(logn)
操作2:由于操作1已经实现了,直接在树状数组总取 查询点对应离散化后的点的值即可
set+treap代码:
//treap #include <cstdio> #include <cmath> #include <cstring> #include <string> #include <algorithm> #include <iostream> #include <queue> #include <map> #include <set> #include <vector> using namespace std; #include <iostream> using namespace std; #define MAXN 200010 struct data{ int l,r,v,size,rnd,w; }; class tp { public: int n,size,root,ans; tp() { n=size=root=ans=0; } data tr[MAXN]; void update(int k)//更新结点信息 { tr[k].size=tr[tr[k].l].size+tr[tr[k].r].size+tr[k].w; } void rturn(int &k) { int t=tr[k].l;tr[k].l=tr[t].r;tr[t].r=k; tr[t].size=tr[k].size;update(k);k=t; } void lturn(int &k) { int t=tr[k].r;tr[k].r=tr[t].l;tr[t].l=k; tr[t].size=tr[k].size;update(k);k=t; } void insert(int &k,int x) { if(k==0) { size++;k=size; tr[k].size=tr[k].w=1;tr[k].v=x;tr[k].rnd=rand(); return; } tr[k].size++; if(tr[k].v==x)tr[k].w++;//每个结点顺便记录下与该节点相同值的数的个数 else if(x>tr[k].v) { insert(tr[k].r,x); if(tr[tr[k].r].rnd<tr[k].rnd)lturn(k);//维护堆性质 } else { insert(tr[k].l,x); if(tr[tr[k].l].rnd<tr[k].rnd)rturn(k); } } void del(int &k,int x) { if(k==0)return; if(tr[k].v==x) { if(tr[k].w>1) { tr[k].w--;tr[k].size--;return;//若不止相同值的个数有多个,删去一个 } if(tr[k].l*tr[k].r==0)k=tr[k].l+tr[k].r;//有一个儿子为空 else if(tr[tr[k].l].rnd<tr[tr[k].r].rnd) rturn(k),del(k,x); else lturn(k),del(k,x); } else if(x>tr[k].v) tr[k].size--,del(tr[k].r,x); else tr[k].size--,del(tr[k].l,x); } int query_rank(int k,int x) { if(k==0)return 0; if(tr[k].v==x)return tr[tr[k].l].size+1; else if(x>tr[k].v) return tr[tr[k].l].size+tr[k].w+query_rank(tr[k].r,x); else return query_rank(tr[k].l,x); } int query_num(int k,int x) { if(k==0)return 0; if(x<=tr[tr[k].l].size) return query_num(tr[k].l,x); else if(x>tr[tr[k].l].size+tr[k].w) return query_num(tr[k].r,x-tr[tr[k].l].size-tr[k].w); else return tr[k].v; } void query_pro(int k,int x) { if(k==0)return; if(tr[k].v<x) { ans=k;query_pro(tr[k].r,x); } else query_pro(tr[k].l,x); } void query_sub(int k,int x) { if(k==0)return; if(tr[k].v>x) { ans=k;query_sub(tr[k].l,x); } else query_sub(tr[k].r,x); } }; tp sp1,sp2; multiset<int> q1,q2; multiset<int>::iterator t1,t2; int main() { freopen( "environment.in","r",stdin ); //scanf 从1.txt输入 freopen( "environment.out","w",stdout ); //printf输出到1.tx int n,i,op; int aa,bb; scanf("%d", &n); int root; int d=0; int ddd=1; int cnt=0; for( i = 1; i <= n; i++) { scanf("%d",&op); if (op==1) { scanf("%d%d",&aa,&bb); aa=aa+d; bb=bb+d; sp1.insert(sp1.root,aa); sp2.insert(sp2.root,bb); q1.insert(aa); q2.insert(bb); cnt++; } else { int t3,t4; scanf("%d",&aa); t1=q1.upper_bound(aa); t2=q2.lower_bound(aa); if (t1==q1.end()) t3=cnt+1; else t3=sp1.query_rank(sp1.root,*t1); if (t2==q2.end()) t4=cnt+1; else t4=sp2.query_rank(sp2.root,*t2); d=(1+cnt-t4)- (1+cnt-t3); printf("%d\n",d); } } return 0; }
离散化做法 :
#include <cstdio> #include <cmath> #include <cstring> #include <string> #include <algorithm> #include <iostream> #include <queue> #include <map> #include <set> #include <vector> using namespace std; #include <iostream> using namespace std; #define MAXN 200010 int n; int tree[MAXN]; struct node { int x,num; //把原始数据 的值 与原始序号储存 bool operator <(const node& b )const {return x<b.x;} bool operator >(const node& b )const {return x>b.x;} bool operator == (const node& b )const {return x==b.x;} node(){} node(int i,int k){x=i;num=k;} }; int cmp(node a,node b) { return a.x<b.x; //把原始数据按值排序, } int max(int a,int b ) { if (a<b)return b;return a; } inline int lowbit(int x) { return x&-x; } void add(int x,int value) { for (int i=x;i<=n;i=i+lowbit(i)) { tree[i]+=value; } } int get(int x) { int sum=0; for (int i=x;i;i-=lowbit(i)) { sum+=tree[i]; } return sum; } struct op { int p; int a,b; }; op ope[MAXN]; node point[MAXN]; set<int> vis; int main() { freopen( "environment.in","r",stdin ); //scanf 从1.txt输入 freopen( "environment.out","w",stdout ); //printf输出到1.tx int i,aa,bb,j; int op; scanf("%d",&n); int cnt=0; for (i=1;i<=n;i++) { scanf("%d",&op); if (op==1) { scanf("%d%d",&aa,&bb); ope[i].p=1; ope[i].a=aa; ope[i].b=bb; } else { scanf("%d",&aa); ope[i].p=2; ope[i].a=aa; if (vis.find(aa)!=vis.end()) continue; vis.insert(aa); point[++cnt].x=aa; point[cnt].num=cnt; } } sort(point+1,point+1+cnt,cmp); //对原始数据按值排升序 int d=0; for (i=1;i<=n;i++) { if (ope[i].p==1) { int l=d+ope[i].a; int r=d+ope[i].b; int lp=lower_bound(point+1,point+1+cnt,node(l,1))-point; int rp=upper_bound(point+1,point+1+cnt,node(r,1))-point; add(lp,1); add(rp,-1); } else { int position=lower_bound(point+1,point+cnt+1,node(ope[i].a,1))-point; printf("%d\n",d=get(position)); } } return 0; }