Description
小 S 热爱大自然, 一天他种了一棵奇怪的线段树.
奇怪的线段树是一种与普通线段树类似的结构, 唯一不同的是, 它不一定以每一个区间的中点作为分治中心.
麻烦的是, 小 S 的线段树被风吹散了, 散成了一个个表示单一区间的结点, 而且正在逐渐飘远. 不过小 S 早有准备, 他可以进行抓取操作, 每一次他可以给出一个抓取区间, 由于这个抓取区间只有两个端点有磁力, 所以只能抓取满足与抓取区间有交而不被抓取区间包含的所有线段树结点.
现在小 S 进行了若干次抓取操作, 对于每次操作, 他希望你能回答他一共抓取了多少个线段树结点.
Input
第一行两个正整数 N, M 表示线段树的最大长度和抓取操作的次数. 接下来按照先序遍历顺序输入奇怪的线段树每个节点的信息: 如果当
前区间是叶子节点, 则返回, 否则输入一个 mid 表示当前区间 [l, r] 的两个
子区间分别是 [l, mid] 和 [mid + 1, r].
接下来 M 行, 每行两个正整数 L R 表示一次抓取操作.
Output
输出 M 行, 每行一个整数, 表示一次抓取操作的答案.
Sample Input
10 10
3
2
1
7
4
5
6
9
8
8 10
10 10
7 7
7 7
7 10
9 10
10 10
1 3
4 5
6 10
Sample Output
2
3
5
5
5
4
3
1
4
4
Data Constraint
对于 20% 的数据, N, M ≤ 5000.
对于 40% 的数据, N, M ≤ 100000.
对于另外 30% 的数据, L = 1.
对于 100% 的数据, N ≤ 100000, M ≤ 3000000.
题解
与其有交集,且不被包含的,
那么出去这次区间,就是完全没有任何交集的,还有被这个区间包含的,
这样,求被包含的,用离线的方法,还是很简单,用树状数组维护。
code
#include <queue>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#include <time.h>
#define ll long long
#define N 100003
#define M 103
#define db double
#define P putchar
#define G getchar
#define inf 998244353
#define pi 3.1415926535897932384626433832795
using namespace std;
char ch;
void read(int &n)
{
n=0;
ch=G();
while((ch<'0' || ch>'9') && ch!='-')ch=G();
ll w=1;
if(ch=='-')w=-1,ch=G();
while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G();
n*=w;
}
int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
ll abs(ll x){return x<0?-x:x;}
ll sqr(ll x){return x*x;}
void write(ll x){if(x>9) write(x/10);P(x%10+'0');}
struct node
{
int l,r,s;
}t[N*80];
bool cmp(node a,node b)
{
return a.r<b.r || (a.r==b.r && a.s<b.s);
}
int n,m,L,R,ans[N*30],tot;
int ls[N],rs[N],s[N];
int x_(int x){return x&(-x);}
int get(int x)
{
int S=0;
for(int i=x;i;i=i-x_(i))
S=S+s[i];
return S;
}
void ins(int x)
{
for(int i=x;i<=n;i=i+x_(i))
s[i]++;
}
void build(int l,int r)
{
int mid;tot++;
ls[t[tot].l=l]++;rs[t[tot].r=r]++;
if(l==r)return;
read(mid);
build(l,mid);
build(mid+1,r);
}
int main()
{
freopen("strange.in","r",stdin);
freopen("strange.out","w",stdout);
read(n);read(m);tot=0;
build(1,n);ans[0]=tot;
for(int i=1;i<=n;i++)rs[i]=rs[i]+rs[i-1];
for(int i=n;i;i--)ls[i]=ls[i]+ls[i+1];
for(int i=1;i<=m;i++)
tot++,read(t[tot].l),read(t[tot].r),t[tot].s=i,ans[i]=ans[0]-rs[t[tot].l-1]-ls[t[tot].r+1];
sort(t+1,t+1+tot,cmp);
for(int i=1;i<=tot;i++)
if(t[i].s)
{
ans[t[i].s]=ans[t[i].s]-get(t[i].r)+get(t[i].l-1);
}else ins(t[i].l);
for(int i=1;i<=m;i++)
write(ans[i]),P('\n');
return 0;
}