zoukankan      html  css  js  c++  java
  • 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
    ",cnt);
    		for (i=0; i<cnt; i++)
    			printf("%d%s",r[i],i==cnt-1?"
    ":" ");
    	}
    	return 0;
    }
  • 相关阅读:
    Ubuntu安装截图软件shutter
    Ubuntu18.04安装破解版MATLAB2018b
    Ubuntu18.04安装UHD+GNU Radio后找不到USRP B210解决办法
    USRP B210 更改A通道或B通道
    性能测试总结(三)--工具选型篇
    性能测试总结(二)---测试流程篇(转载)
    性能测试总结(一)---基础理论篇(转载)
    selenium 自动化测试面试题及答案
    Appium-测试失败后屏幕截图的
    七 Appium常用方法介绍
  • 原文地址:https://www.cnblogs.com/Blackops/p/5766286.html
Copyright © 2011-2022 走看看