1. 程式人生 > 實用技巧 >習題:Valera and Queries(樹狀陣列)

習題:Valera and Queries(樹狀陣列)

題目

傳送門

思路

正難則反

考慮有哪些節點沒有被任何一條線段所覆蓋

離線之後用一種類似於掃描線的做法即可

程式碼

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
namespace BIT
{
	int N=1000015;
	int b[1000015];
	int lowbit(int x)
	{
		return x&(-x);
	}
	void update(int k,int val)
	{
		for(int i=k;i<N;i+=lowbit(i))
			b[i]+=val;
	}
	int ask(int k)
	{
		int ret=0;
		for(int i=k;i;i-=lowbit(i))
			ret+=b[i];
		return ret;
	}
}
using namespace BIT;
struct node
{
	int l,r,id;
	friend bool operator < (const node &a,const node &b)
	{
		if(a.l!=b.l)
			return a.l>b.l;
		if(a.r!=b.r)
			return a.r<b.r;
		return a.id<b.id;
	}
};
int len;
int n,m;
int ans[300005];
vector<node> a;
int main()
{
	ios::sync_with_stdio(false);
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		int l,r;
		cin>>l>>r;
		a.push_back((node){l,r,0});
	}
	len=n+1;
	for(int i=1,cnt,la;i<=m;i++)
	{
		cin>>cnt;
		ans[i]=n;
		la=0;
		for(int j=1,p;j<=cnt;j++)
		{
			cin>>p;
			a.push_back((node){la+1,p-1,i});
			la=p;
		}
		a.push_back((node){la+1,1000005,i});
	}
	sort(a.begin(),a.end());
	for(int i=0;i<a.size();i++)
	{
		if(a[i].id)
			ans[a[i].id]-=ask(a[i].r);
		else
			update(a[i].r,1);
	}
	for(int i=1;i<=m;i++)
		cout<<ans[i]<<'\n';
	return 0;
}