loj#6270. 数据结构板子题

https://loj.ac/problem/6270

首先可以看出这是 l o g 2 log^2 log2的三维数点问题
然后你就T了

考虑两个区间A,B的情况有
1、A包含B
2、AB相交但不包含
3、B包含A

考虑第1种情况的区间长度大于B的长度
问题可以转化成查询B包含的区间中小于等于区间长度-小于K的数量

我们可以将询问和区间按区间长度排序
查询包含的区间数量是:
右 端 点 在 [ 1 , R ] − 左 端 点 在 [ 1 , L − 1 ] 的 数 量 右端点在[1,R]-左端点在[1,L-1]的数量 [1,R][1,L1]
这个可以用树状数组解决


#include 
#include 
#include 
using namespace std;

#define dd c=getchar()
int read() {int s=0,w=1;char c;while (dd,c>'9' || c<'0') if (c=='-') w=-1;while (c>='0' && c<='9') s=s*10+c-'0',dd;return s*w;}
#undef dd
void write(int x) {if (x<0) putchar('-'),x=-x;if (x>=10) write(x/10);putchar(x%10|'0');}
void wln(int x) {write(x);putchar('\n');}void wsp(int x) {write(x);putchar(' ');}

const int N = 5e5+7;
struct seg {
	int l, r;
	bool operator <(seg a) const {
		return r-l < a.r-a.l;
	}
}a[N];
struct node {
	int l,r,k,v,id;
	bool operator < (node a) const {
		return k < a.k;
	}
}q[N<<1];
int n,m,Q,cnt;
int ans[N];

struct tree {
	int tr[N];
	void add(int x) {for (; x <= n; x+=x&-x) tr[x]++;}
	int query(int x) {
		int ans = 0;
		for (; x; x-=x&-x) ans+=tr[x];
		return ans;
	}
	int query(int l, int r) {return query(r) - query(l-1);}
}t1,t2;
int main() {
//	freopen("mermaid.in", "r", stdin);
//	freopen("mermaid.out", "w", stdout);
	n = read(); Q = read();
	for (int i = 1; i <= n; i++) a[i].l = read(), a[i].r = read();
	for (int i = 1, l, r, K; i <= Q; i++) {
		l = read(); r = read(); K = read();
		if (K-1>r-l) continue;
		q[++cnt]=(node) {l,r,K-1,-1,i};
		q[++cnt]=(node) {l,r,r-l,1,i};
	}
	sort(a+1, a+n+1); sort(q+1, q+cnt+1);
	for (int i = 1, j = 1; i <= cnt; i++) {
		while (j <= n && a[j].r-a[j].l <= q[i].k) {
			t1.add(a[j].l);
			t2.add(a[j].r);
			j++;
		}
		ans[q[i].id]+=q[i].v*(t2.query(q[i].r)-t1.query(q[i].l-1));
	}
	for (int i = 1; i <= Q; i++) wln(ans[i]);
}

你可能感兴趣的:(树状数组)