NBOJv2 1004 蛤瑋打掃教室(線段樹區間更新區間最值查詢)

Problem 1004: 蛤瑋打掃教室


Time Limits:  1000 MS   Memory Limits:  65536 KB

64-bit interger IO format:  %lld   Java class name:  Main


Description

現在知道一共有n個機房,算上蛤瑋一共有m個隊員,教練做了m個籤,每個簽上寫着兩個數L,R(L<=R),抽到的人要把[L,R]的教室全部打掃一遍.由於蛤瑋是隊長而且他很懶,他通過某種交易提前知道了所有m個簽上面寫的是什麼,而且通過某種魔法可以控制自己抽到哪個籤.一個教室被打掃一次就乾淨了,所以蛤瑋想知道自己抽哪些籤可以不用打掃教室而且不會被教練發現,即他抽到的區間全都會被別人打掃一遍.

蛤瑋被教練叫去打掃機房,集訓隊有很多機房,也有很多隊員,現在他們要用抽籤的方式決定誰打掃哪間教室.

 

Input

第一行爲一個整數T(1<=T<=20),代表數據組數。每組數據第一行n,m(1<=n,m<=100000),接下來m行,每行兩個數L,R(1<=L<=R<=n).

 

Output

每組數據輸出一個k,表示多少個籤符合蛤瑋的要求,接下來一行輸出k個數,這些籤的編號,下標從1開始.

 

Sample Input

3
15 5
1 4
5 5
6 8
9 10
5 6
3 6
1 1
1 1
2 2
2 2
3 3
3 3
10 3
1 4
2 6
6 10 

Output for Sample Input

2
2 5
6 1 2 3 4 5 6
0

最近學了線段樹,把以前的題目都拿出來再做了一遍,雖然說時間並比離散化的做法慢很多……主要是熟悉熟悉,這題用線段樹就是區間更新,區間最(小)值查詢,因爲一個區間只有被至少打掃兩次才能被選入,也就是選某些區間的最小值大於等於2的即可,pushdown函數稍微修改一下就好了

代碼:

#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<sstream>
#include<cstring>
#include<cstdio>
#include<string>
#include<deque>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
using namespace std;
#define INF 0x3f3f3f3f
#define MM(x,y) memset(x,y,sizeof(x))
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
typedef pair<int,int> pii;
typedef long long LL;
const double PI=acos(-1.0);
const int N=100010;
struct info
{
	int l,mid,r;
	int maxm,add;
};
info T[N<<2];
void pushup(int k)
{
	T[k].maxm=min(T[LC(k)].maxm,T[RC(k)].maxm);
}
void pushdown(int k)
{
	T[LC(k)].add+=T[k].add;
	T[RC(k)].add+=T[k].add;
	T[LC(k)].maxm+=T[k].add;
	T[RC(k)].maxm+=T[k].add;
	T[k].add=0;
}
void build(int k,int l,int r)
{
	T[k].l=l;
	T[k].r=r;
	T[k].mid=MID(l,r);
	T[k].add=0;
	T[k].maxm=0;
	if(l==r)
		return ;
	build(LC(k),l,T[k].mid);
	build(RC(k),T[k].mid+1,r);
}
void update(int k,int l,int r,int v)
{
	if(r<T[k].l||l>T[k].r)
		return ;
	if(l<=T[k].l&&r>=T[k].r)
	{
		T[k].add+=v;
		T[k].maxm+=v;
	}	
	else
	{
		if(T[k].add)
			pushdown(k);
		update(LC(k),l,r,v);
		update(RC(k),l,r,v);
		pushup(k);
	}
}
int query(int k,int l,int r)
{
	if(l<=T[k].l&&r>=T[k].r)
		return T[k].maxm;
	if(T[k].add)
		pushdown(k);
	if(r<=T[k].mid)
		return query(LC(k),l,r);
	else if(l>T[k].mid)
		return query(RC(k),l,r);
	else
		return min(query(LC(k),l,T[k].mid),query(RC(k),T[k].mid+1,r));
}
pii seg[N];
int main(void)
{
	int tcase,n,m,l,r,i,j,cnt;
	scanf("%d",&tcase);
	while (tcase--)
	{
		scanf("%d%d",&n,&m);
		build(1,1,n);
		for (i=1; i<=m; i++)
		{
			scanf("%d%d",&seg[i].first,&seg[i].second);
			update(1,seg[i].first,seg[i].second,1);
		}
		vector<int>r;
		for (i=1; i<=m; i++)
		{
			int m=query(1,seg[i].first,seg[i].second);
			if(m>=2)
				r.push_back(i);
		}
		cnt=r.size();
		printf("%d\n",cnt);
		for (i=0; i<cnt; i++)
			printf("%d%s",r[i],i==cnt-1?"\n":" ");
	}
	return 0;
}

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