1877: 蛤玮打扫教室
Time Limit: 2 Sec Memory Limit: 128 MBSubmit: 555 Solved: 132
Submit Status Web Board
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
315 51 45 56 89 105 63 61 11 12 22 23 33 310 31 42 66 10
Sample Output
22 561 2 3 4 5 60
HINT
Source
线段树模板题,lazy数组的应用
延迟标记:http://blog.csdn.net/zip_fan/article/details/46775633
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<limits.h>
#include<algorithm>
using namespace std;
int sum[200005*2],q[200005*2],lazy[200005*2];
struct node
{
int x,y;
}a[200005*8];
void pushdown(int id)
{
if(lazy[id])
{
sum[id*2]+=lazy[id];
sum[id*2+1]+=lazy[id];
lazy[id*2]+=lazy[id];
lazy[id*2+1]+=lazy[id];
lazy[id]=0;
}
}
int query(int L, int R,int l,int r,int id)
{
int ret=10000000;
if(L<=l && R>=r)
return sum[id];
pushdown(id);
int m=(l+r)/2;
if(L<=m)
ret=min(ret,query(L,R,l,m,id*2));
if(R>m)
ret=min(ret,query(L,R,m+1,r,id*2+1));
return ret;
}
void updata(int L,int R,int l,int r,int rt,int add)
{
int m;
if(L<=l && R>=r)
{
sum[rt]+=add;
lazy[rt]+=add;
return;
}
pushdown(rt);
m=(l+r)/2;
if(L<=m)
updata(L,R,l,m,rt*2,add);
if(R>m)
updata(L,R,m+1,r,rt*2+1,add);
sum[rt]=min(sum[rt*2],sum[rt*2+1]);
}
int main()
{
int T,n,m,i,j,ans,k;
scanf("%d",&T);
while(T--)
{
k=0;
memset(sum,0,sizeof(sum));
memset(lazy,0,sizeof(lazy));
scanf("%d%d",&n,&m);
for(i=1;i<=m;i++)
{
scanf("%d%d",&a[i].x,&a[i].y);
updata(a[i].x,a[i].y,1,n,1,1);
}
for(i=1;i<=m;i++)
{
int tmp=query(a[i].x,a[i].y,1,n,1);
if(tmp>=2)
q[++k]=i;
}
printf("%d\n",k);
if(k>0)
printf("%d",q[1]);
for(i=2;i<=k;i++)
printf(" %d",q[i]);
if(k>0)
printf("\n");
}
}