zoukankan      html  css  js  c++  java
  • Problem 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
    

    Hint

     

    Author

    2016郑州轻工业学院校赛

    这题应该是线段树,但是没学过也感觉看不太懂,于是找了其他大牛题解的做法,还好这种做法容易懂些。

    思路:在vis数组里对每一个区间的L与R操作,vis[L]++,vis[R+1]--,这样可以标记一个区间的端点,然后再用这个数组求一个前缀和放入per,每一项即是对应点的被覆盖次数,然后这样就稍微好办了点,转化为告诉你每一个点的覆盖次数,求是否题目中的抽签的区间是否全部都是至少被覆盖两次的点,然后再开一个cnt数组,记录连续完整覆盖的区间长度。最后比较每一个抽签R-L+1(区间长度)与cnt[R]-cnt[L-1](连续覆盖区间长度)是否相等即可。不愧是大牛想出来的办法。

    代码:

    #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>
    #define INF 0x3f3f3f3f
    #define MM(x) memset(x,0,sizeof(x))
    using namespace std;
    typedef long long LL;
    const int N=100010;
    struct info
    {
    	int l;
    	int r;
    };
    info point[N];//抽签信息记录
    int vis[N];//端点标记
    int cnt[N];//连续覆盖次数大于2区间
    int ans[N];//记录答案
    int per[N];//单点覆盖次数
    int main(void)
    {
    	int tcase,i,j,L,R,x,y,z,n,m;
    	scanf("%d",&tcase);
    	while (tcase--)
    	{
    		MM(point);MM(vis);MM(cnt);MM(ans);MM(per);
    		scanf("%d%d",&n,&m);
    		for (i=1; i<=m; i++)
    		{
    			scanf("%d%d",&point[i].l,&point[i].r);
    			vis[point[i].l]++;
    			vis[point[i].r+1]--;
    		}
    		int temp=0;
    		for (i=1; i<=n; i++)
    		{
    			temp+=vis[i];
    			per[i]=temp;
    		}
    		for (i=1; i<=n; i++)
    		{
    			if(per[i]>=2)
    				cnt[i]=cnt[i-1]+1;
    			else
    				cnt[i]=0;//或cnt[i]=cnt[i-1]也可以,反正最后求的是差值
    		}
    		int k=0;
    		for (i=1; i<=m; i++)
    		{
    			int left=point[i].l;
    			int righ=point[i].r;
    			if(righ-left+1==cnt[righ]-cnt[left-1])
    				ans[k++]=i;
    		}
    		printf("%d
    ",k);
    		for (i=0; i<k; i++)
    			printf("%d%s",ans[i],i==k-1?"
    ":" ");
    	}
    	return 0;
    }
  • 相关阅读:
    c#生成图片验证码
    关于Aspcms如何嵌入整个网站,以及网站导航所指向页面的内容显示
    web 验证控件
    MVC Link连接数据库增删改查方法的不同写法
    Mvc 翻页查询,代码很有用
    MVC添加分布视图做唯一验证
    MVc路由查询,路由到底有什么作用呢??
    MVC添加动态视图的参考代码。重点是添加部分视图的使用方法,非常有用的代码!!!!!!!!!!!!!!
    tyvj P1209
    bzoj 1051: [HAOI2006]受欢迎的牛 tarjan缩点
  • 原文地址:https://www.cnblogs.com/Blackops/p/5766340.html
Copyright © 2011-2022 走看看