题意: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;
}