libreoj 6270 數據結構板子題 題解

博客觀賞效果更佳

題意簡述

給定 nn 個區間 [li,ri][l_i,r_i],和 QQ 個詢問,每次給你三個整數 [l,r,k][l,r,k],求被 [l,r][l,r] 完全包含且長度 k\ge k 的區間數量。

注:定義一個區間 [l,r][l,r] 的長度是 rlr-l

n,q106n,q\le 10^61li,ri,l,r,kn1\le l_i,r_i,l,r,k\le nli<ri,l<rl_i<r_i,l<r

思路

如果沒有 kk 的限制,只是要求完全包含的區間數量,可以用兩個樹狀數組,然後計算右端點在 [1,r][1,r] 中的數量減去左端點在 [1,l1][1,l-1] 中的數量。

然後現在有了 kk 的限制,我們把一個詢問拆成 [l,r,rl][l,r,r-l] 減去 [l,r,k1][l,r,k-1]。然後把詢問和區間都按長度排序,一個一個處理即可。還有就是記錄一下這個答案屬於第幾個詢問,帶正號還是帶負號

[l,r,rl][l,r,r-l] 帶正號,[l,r,k1][l,r,k-1] 帶負號,看上面答案是怎麼算的)

然後就做完了。

代碼

{% fold %}

#include <bits/stdc++.h>
using namespace std;
namespace Flandre_Scarlet
{
	#define N 1666666
	#define F(i,l,r) for(int i=l;i<=r;++i)
	#define D(i,r,l) for(int i=r;i>=l;--i)
	#define Fs(i,l,r,c) for(int i=l;i<=r;c)
	#define Ds(i,r,l,c) for(int i=r;i>=l;c)
	#define MEM(x,a) memset(x,a,sizeof(x))
	#define FK(x) MEM(x,0)
	#define Tra(i,u) for(int i=G.Start(u),v=G.To(i);~i;i=G.Next(i),v=G.To(i))
	#define p_b push_back
	#define sz(a) ((int)a.size())
	#define iter(a,p) (a.begin()+p)
	int I()
	{
	    int x=0;char c=getchar();int f=1;
	    while(c<'0' or c>'9') f=(c=='-')?-1:1,c=getchar();
	    while(c>='0' and c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	    return (x=(f==1)?x:-x);
	}
	void Rd(int cnt,...)
	{
	    va_list args; va_start(args,cnt);
	    F(i,1,cnt) {int* x=va_arg(args,int*);(*x)=I();}
	    va_end(args);
	}
	class BIT
	{
	public:
	    int tree[N],len;
	    void Build(int _len) {FK(tree); len=_len;}
	    void Add(int pos,int x)
	    {
	        while(pos<=len) tree[pos]+=x,pos+=(pos&(-pos));
	    }
	    int Query(int pos)
	    {
	        int ans=0;
	        while(pos>0) ans+=tree[pos],pos-=(pos&(-pos));
	        return ans;
	    }
	}L,R;
	struct seg{int l,r;}a[N]; bool operator<(seg a,seg b){return a.r-a.l<b.r-b.l;}
    // 給定的線段,按長度排序
	struct que{int l,r,k,id,tp;}q[N]; bool operator<(que a,que b){return a.k<b.k;}
	// 詢問,也是按長度排序
    
	int n,m; int cnt=0;
	void Input()
	{
		Rd(2,&n,&m);
		F(i,1,n) {a[i].l=I(); a[i].r=I();}
		F(i,1,m) 
		{
			int l,r,k; Rd(3,&l,&r,&k);
			if (k>r-l) continue;
			q[++cnt]=(que){l,r,r-l,i,1}; // 記錄編號和符號
			q[++cnt]=(que){l,r,k-1,i,-1};
		}
	}

	int ans[N];
	void Soviet()
	{	
		sort(a+1,a+n+1); sort(q+1,q+cnt+1);
		L.Build(n); R.Build(n); // 兩顆樹狀數組,記錄左端點和右端點

		int pos=1;
		F(i,1,cnt)
		{
			while(pos<=n and a[pos].r-a[pos].l<=q[i].k) 
			{
				L.Add(a[pos].l,1); R.Add(a[pos].r,1); ++pos;
			}
			ans[q[i].id]+=q[i].tp*(R.Query(q[i].r)-L.Query(q[i].l-1));
		} 
		F(i,1,m) printf("%d\n",ans[i]); 
	}

	#define Flan void
	Flan IsMyWife()
	{
		Input();
		Soviet();
	}
}
int main()
{
	Flandre_Scarlet::IsMyWife();
	getchar();getchar();
	return 0;
}

{% endfold %}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章