首页 > 试题广场 >

重叠的装饰

[编程题]重叠的装饰
  • 热度指数:4679 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
我们部门需要装饰墙,但是墙非常非常的长,有一千万米。我们会按顺序贴很多海报在上面,这些海报相互之间会重叠,请问下,最后还能看到哪些?(只看到一部分也算)

输入描述:
N表示N张海报
接下来每一行代表海报的左右边界(上下默认全满),Li,Ri,均为整数,大于0,小于一千万。海报按输入顺序张贴。


输出描述:
有多少张海报是可见的
示例1

输入

5
1 4
2 6
8 10
3 4
7 10

输出

4
"""
一个实现起来很简单的思路,通过80%用例,考试时很实用,不知道改成C或java是不是还超时
对于示例1,所有左右边界组成的集合(1, 2, 3, 4, 6, 7, 8, 10),分成七段;
借助字典从前到后为每一段赋值海报编号,
最后 每一段的值代表最上边可以看到的海报编号,
对字典的值求集合的长度,即为可见海报的张数
"""
import sys

if __name__ == "__main__":
    # sys.stdin = open("input.txt", "r")
    n = int(input().strip())
    a = []
    for _ in range(n):
        a.append(list(map(int, input().strip().split())))
    b = sorted(list(set(sum(a, []))))
    d = dict()
    for i in range(n):
        for j in range(b.index(a[i][0]), b.index(a[i][1])):
            d[str(b[j]) + '-' + str(b[j + 1])] = i
    ans = len(set(d.values()))
    print(ans)  

第二种思路
/*
对每一张海报t,
计算上一层海报未覆盖的(可见)区域(x,y),
递归调用,直到t>n,海报t仍可以被看到,返回True;
或者直到某一层将可见区域完全覆盖,返回False。
by the way: 最后一个测试用例是错的吧,通过仔细对比已通过程序,26行改为27行通过全部用例 
*/
#include<bits/stdc++.h>
using namespace std;
#define N 10000
int n;
int a[N][2];

bool cover(int  x, int  y, int t)
{
    if (x >= y)
        return false;
    if (t >= n)
        return true;
    if (a[t][0] <= x && y <= a[t][1])
        return false;
    else if (a[t][0] >= y || a[t][1] <= x)
        return cover(x, y, t + 1);
    else if (x <= a[t][0] && a[t][1] <= y)
//        return cover(x, a[t][0], t + 1) || cover(a[t][1], y, t + 1)
        return cover(x, y, t + 1);
    else if (x < a[t][1] && a[t][1] < y)
        return cover( a[t][1], y, t + 1);
    else if (x < a[t][0] && a[t][0] < y)
        return cover( x, a[t][0], t + 1);
    return false;//所有情况都考虑到了,此句不需要;删除此句有时会编译不通过
}

int main()
{
//    freopen("input.txt", "r", stdin);
    cin >> n;
    for(int i = 0; i < n; i++) {
        cin >> a[i][0] >> a[i][1];
    }
    int ans = 0;
    for(int t = 0; t < n; t++)
        if(cover(a[t][0], a[t][1], t + 1))
            ans += 1;
    cout << ans << endl;
    return 0;
}

编辑于 2019-07-11 17:45:05 回复(6)
这道题有问题吧。输入要是:
4
1 10
2 8
1 2
8 10
最后通过的程序输出为4,正确答案是3吧。第一张被遮的严严实实。
发表于 2019-07-25 10:48:50 回复(5)
#include <bits/stdc++.h>
using namespace std;

int main(){
    int n, x, y, Min=INT_MAX, Max=0;
    vector<int> m(10000001, 0);
    scanf("%d", &n);
    for(int i=1;i<=n;i++){
        scanf("%d%d", &x, &y);
        Min = min(Min, x);
        Max = max(Max, y);
        for(int j=x;j<=y;j++)
            m[j] = i;
    }
    set<int> S;
    for(int i=Min;i<=Max;i++)
        if(m[i])
            S.insert(m[i]);
    cout<<S.size()<<endl;
    return 0;
}

发表于 2020-10-30 08:53:15 回复(0)
#优化过的顺序dp插入判断方法,很好理解,百分百通过
def main():
    N = int(input())
    k = [[0, i, -1] for i in range(N*2)]
    maxs = 0
    i = 0
    while i < N*2:
        a, b = map(int, input().split())
        k[i][0] = a
        k[i+1][0] = b
        i += 2
#    print(k)
    k.sort(key=lambda x:x[0])
    k[0][2] = 0
    count = 0
    for i in range(1, len(k)):
        if k[i][2] == k[i-1][2]:
            k[i][2] = count
        else:
            count += 1
            k[i][2] = count
#    print("count", count)
    dp = [-1] * (count+1)
#    print(k)
    k.sort(key=lambda x:x[1])
#    print(k)
    i = 0
#    print(dp)
    while i < len(k):
        left = k[i][2]
        right = k[i+1][2]
        for j in range(left, right+1, 1):
            dp[j] = i
        i += 2
#    print(dp)
    dic = dict()
    for i in range(len(k)):
        dic[dp[i]] = dic.get(dp[i], 0)+1
#    print(dic)
    print(len(dic))
if __name__ == "__main__":
    main()

编辑于 2020-04-11 14:35:31 回复(0)
楼上大佬的做法给了启发,但是发现其实不需要线段树的,线段树的查询、插入复杂度应该为O(logn), 更新操作是对某个值操作复杂度也为O(logn),但是这里显然不是修改某个值,而是修改某个区间,且复杂度也不是O(logn).
#include<iostream>
#include<unordered_map>
#include<string>
#include<vector>
#include<algorithm>
#include<unordered_set>
using namespace std;
int main(){
int n;
while(cin>>n){
vector<pair<int,int>> nums(n);
for(int i=0; i<n; i++) cin>>nums[i].first>>nums[i].second;
vector<int> digits(n*2);
for(int i=0; i<n; i++){
digits[i*2] = nums[i].first;
digits[i*2+1] = nums[i].second;
}
sort(digits.begin(), digits.end());
digits.erase(unique(digits.begin(), digits.end()), digits.end());
unordered_map<int,int> intMap;
for(int i=0; i<digits.size(); i++) intMap[digits[i]] = i;
for(int i=0; i<n; i++){
nums[i].first = intMap[nums[i].first];
nums[i].second = intMap[nums[i].second];
}

digits.assign(digits.size(), -1); //至多digits.size()-1个区间
for(int i=0; i<nums.size(); i++){
for(int j=nums[i].first+1; j<=nums[i].second; j++){
digits[j] = i;
}
}
unordered_set<int> intS;
for(auto val : digits) intS.insert(val);
if(intS.find(-1)!=intS.end()) cout<<intS.size()-1<<endl;
else cout<<intS.size()<<endl;
}
return 0;
}

编辑于 2019-07-07 15:26:39 回复(0)

招商银行信用卡中心2019秋招IT笔试(AI、开发、测试开发方向)第一批

https://blog.csdn.net/FlushHip/article/details/84137906

我感觉数据有误

发表于 2018-11-19 12:52:12 回复(0)
#include<bits/stdc++.h>
using namespace std;
const int max_n = 1e5;
//int seg[4*max_n];
// 懒惰标记,用于延迟传播
int add[4*max_n];
// 建树
//void create(int l,int r,int rt)
//{
//    if(l==r)
//        return;
//    create(l,(l+r)>>1,rt<<1);
//    create(((l+r)>>1)+1,r,rt<<1|1);
//}
// 下推函数
void pushDown(int rt)
{
    if(add[rt])
    {
        // 将标记下推到左右子区间
        add[rt<<1] = add[rt]; 
        add[rt<<1|1] = add[rt];
        // 清除本节点的标记
        add[rt] = 0;
    }
}
void update(int L,int R,int l,int r,int rt,int val)
{
    if(L<=l&&R>=r)
    {
        add[rt] = val; //子区间仍需要根据add值进行调整
        return;
    }
    //if(l==r)  //  叶子节点更新
    //{
    //    add[rt] = val;
    //    return;
    //}
    // 下推标记
    pushDown(rt);
    // 继续寻找区间
    int mid = (l+r)>>1;
    if(L<=mid) update(L,R,l,mid,rt<<1,val);
    if(R>mid) update(L,R,mid+1,r,rt<<1|1,val);

}
// 区间查询不重复的海报数目
void query(int l,int r,int rt,set<int>& se)
{
    if(add[rt])
    {
       // if(l==r)
       // {
            se.insert(add[rt]);
            return;
      //  }
       // else pushDown(rt);
    }
    // 到叶节点了 返回
    if(l==r) return;
    query(l,(l+r)>>1,rt<<1,se);
    query(((l+r)>>1)+1,r,rt<<1|1,se);
}
int main()
{
    int n;
    cin>>n;
    int a,b;
    vector<pair<int,int>>data;
    // 辅助数组
    vector<int>xs;
    for(int i=1;i<=n;++i)
    {
       cin>>a>>b;
       data.push_back({a,b});
       xs.push_back(a);
       xs.push_back(b);
    }
    // 排序
    sort(xs.begin(),xs.end());
    // 去重
    xs.erase(unique(xs.begin(),xs.end()),xs.end());
    //create(1,xs.size(),1);
    set<int>se;
    for(int i=1;i<=n;++i)
    {
        // 离散化 节约线段树需要开辟的空间
       int l = lower_bound(xs.begin(),xs.end(),data[i-1].first)-xs.begin()+1;
       int r = lower_bound(xs.begin(),xs.end(),data[i-1].second)-xs.begin()+1;
        // 更新
       update(l,r,1,xs.size(),1,i);
    }
    // 统计数目
    query(1,xs.size(),1,se);
    cout<<se.size()<<endl;
    return 0;
}
编辑于 2020-05-08 00:15:01 回复(1)
模拟插入过程,正确率80%
#include<iostream>
#include<vector>
#include<algorithm>
#include<set>
#include<cstring>

using namespace std;

int mp[10000001] ={0};

int main(){
    int n;
    cin>>n;
    int x,y;
    for(int i = 1; i <= n; ++i){
        cin>>x>>y;
         for(int j = x;j <= y; ++j){
             mp[j] = i;
         }
    }
    set<int> num;
    for(int& k : mp){
        if(k>0) num.insert(k);
    }
    cout<<num.size()<<endl;
    return 0;
}


发表于 2019-08-14 11:59:54 回复(1)
//代码有注释,AC
#include <bits/stdc++.h>
 using namespace std; 

int main(void)
{
    int n;
    cin>>n;
    vector<int> m(10000001,0);
    //用10000001的数组存储墙的每一米
    int a;
    int b;
    int min_value=10000000;
    int max_value=1;
    for(int i = 1;i<=n;i++)
    {
        cin>>a;
        cin>>b;
        //记录下范围,后边就不用从1遍历到最后一个
        min_value = min(min_value,a);
        max_value = max(max_value,b);
        //贴一张海报,把每一米墙用这个编号代替
        for(int j =a;j<=b;j++)
            m[j] = i;
    }
    set<int> ms;
   //统计剩余不重复的编号
    for(int i =min_value;i<=max_value;i++)
    {
        //非0才可以
       if(m[i]!=0)
        ms.insert(m[i]);
    }
    cout<<ms.size();
}


发表于 2020-03-08 23:31:58 回复(0)
import java.util.*;
public class Main {
    public static void main(String args[]) {
        int min = Integer.MAX_VALUE;
        int max = -1;
        Scanner in = new Scanner(System.in);
        int N = in.nextInt();
        int[] temp = new int[10000001];
        for(int i = 1; i <= N; i++) {
            int Li = in.nextInt();
            int Ri = in.nextInt();
            min = Math.min(Li,Ri);
            max = Math.max(Ri,Li);
            for(int j = min; j <= max; j++) {
                temp[j] = i;
            }
        }
        Set<Integer> set = new HashSet<>();
        for(int i = 0; i < temp.length; i++) {
            if(temp[i] != 0) 
                set.add(temp[i]);
        }
        System.out.println(set.size());
    }
}

发表于 2021-05-26 20:26:40 回复(0)
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        Set <Integer> set = new HashSet<>();
        int T[]= new int[10000001];
        Arrays.fill(T,-1);
        int n = in.nextInt();
        int [][]arr = new int[n][2];
        for(int i=0;i<n;i++){
            arr[i][0]=in.nextInt();
            arr[i][1]=in.nextInt();
        }
        for(int i=0;i<n;i++){
            for(int j=arr[i][0];j<=arr[i][1];j++){
                T[j]=i;
            }
        }
        for(int i=0;i<10000001;i++){
            if(T[i]==-1) continue;
            set.add(T[i]);
        }
        System.out.println(set.size());
    }
}

发表于 2021-04-22 16:41:22 回复(0)
n = int(input())
a = [0 for i in range(100000)]
for i in range(n):
    l, r = list(map(int,input().split()))
    a[l:r+1] = [i+1]*(r-l+1)
print(len(set(a))-1)

发表于 2020-10-30 18:15:06 回复(0)
线段树,思路是反向覆盖,若当前海报会被之后的海报覆盖,则忽略,否则count + 1

同只通过80%
import java.util.Scanner;

public class Main {
    private static int count = 0;
    private static boolean flag = false;

    public static void main(String[] args) throws InterruptedException {
        Scanner scanner = new Scanner(System.in);

        int N = scanner.nextInt();
        int[][] input = new int[N][2];
        int leftBound = Integer.MAX_VALUE, rightBound = Integer.MIN_VALUE;

        for (int i = 0; i < N; i++) {
            input[i][0] = scanner.nextInt();
            input[i][1] = scanner.nextInt();
            leftBound = Math.min(leftBound, input[i][0]);
            rightBound = Math.max(rightBound, input[i][1]);
        }

        Node root = buildSegmentTree(leftBound, rightBound);

        for (int i = N - 1; i >= 0; i--) {
            flag = false;
            insertSegment(input[i][0], input[i][1], root);
        }

        System.out.println(count);
    }



    public static void insertSegment(int left, int right, Node node) {
        if (left == right) {
            if (node.cover == 0) {
                node.cover = 1;
                if (!flag) {
                    count++;
                    flag = true;
                }
            }

            return;
        }


        int mid = (node.left + node.right) >>> 1;

        if (right <= mid) insertSegment(left, right, node.leftChild);
        else if (left > mid) insertSegment(left, right, node.rightChild);
        else {
            insertSegment(left, mid, node.leftChild);
            insertSegment(mid + 1, right, node.rightChild);
        }

        if (node.leftChild.cover == 1 && node.rightChild.cover == 1) node.cover = 1;
    }

    public static Node buildSegmentTree(int left, int right) {
        Node node = new Node();
        node.left = left;
        node.right = right;
        node.cover = 0;

        if (left == right) {
            return node;
        }

        int mid = (left + right) >>> 1;

        node.leftChild = buildSegmentTree(left, mid);
        node.rightChild = buildSegmentTree(mid + 1, right);

        return node;
    }
}


class Node {
    int left, right, cover;
    Node leftChild, rightChild;
}


发表于 2020-07-29 10:58:11 回复(0)
#include <iostream>
(720)#include <string>
#include <vector>
(721)#include <map>
using namespace std;

int main() {

    //cout << "jisenquan" << endl;
    vector<pair<int, int>> data;
    int n;
    int res;
    cin >> n;
    for (int i = 1; i <= n; i++) {
        pair<int, int> temp;
        cin >> temp.first >> temp.second;
        data.push_back(temp);
    }

    map<int, int> m1;
    m1[data[n - 1].first] = data[n - 1].second;
    res = 1;
    for (int i = n - 2; i >= 0; i--) {
        pair<int, int> temp = data[i];
        bool flag = true;
        for (auto it = m1.begin(); it != m1.end(); it++) {
            if (temp.first >= it->first && temp.second <= it->second) {
                flag = false;
                break;
            }
            if (it->second < temp.first || temp.second < it->first) {
                continue;
            }
            auto it2 = it;
            it2++;
            while (it2 != m1.end() && it2->first <= temp.second) {
                if (it2->second >= temp.second) {
                    it2++;
                    break;
                }
                it2++;
            }
            it2--;
            temp.first = it->first > temp.first ? temp.first : it->first; 
            if (it2 != m1.end())
            {
                temp.second = temp.second > it2->second ? temp.second : it2->second;
            }
            it2++;
            m1.erase(it, it2);
            //it = it2;
            break;
        }
        if (flag) {
            res++;
            m1[temp.first] = temp.second;
        }
    }

    cout << res << endl;
    //system("Pause");
    return 0;
}
发表于 2020-05-11 19:49:55 回复(0)
import java.util.*;
public class Main{

    public static void main(String[] args){
        //输入
        Scanner scanner = new Scanner(System.in);
        int num = scanner.nextInt();
        if(num==0||num==1) {
            System.out.println(num);
            return;
        }
        scanner.nextLine();
        String[] str = new String[num];
        for(int i=0;i<num;i++) {
            if(scanner.hasNext()) {
                String s = scanner.nextLine();
                str[i] = s;
            }
        }
        scanner.close();
        if(str==null){
            System.out.println(0);
            return;
        }
        ArrayList<Node> arr = new ArrayList<Node>();
        for(String s:str) {
            String[] s1 = s.split(" ");
            int leftval = Integer.valueOf(s1[0]);
            int rightval = Integer.valueOf(s1[1]);
            arr.add(new Node(leftval,rightval));
        }
        //把第一张海报贴到墙上
        ArrayList<ArrayList<Node>> Wall = new ArrayList<ArrayList<Node>>();
        ArrayList<Node> poster1 = new ArrayList<Node>();
        poster1.add(arr.get(0));
        Wall.add(poster1);
        //每加入一张海报,先对墙上的每一个海报段求补集,修改原来的海报段露出的部分的区间
        for(int i=1;i<arr.size();i++) {//新加入的海报
            for(int j=0;j<Wall.size();j++) {//已经贴好的每一张海报
                int index = Wall.get(j).size();
                for(int k=0;k<index;k++) {//每张海报段
                    ArrayList<Node> newPosterDuan = Overlap
                        (Wall.get(j).get(k),arr.get(i));//老海报段对新海报的补集
                    if(newPosterDuan==null) {
                        Wall.get(j).set(k,null);
                    }else {
                        Wall.get(j).remove(k);
                        for(int m=0;m<newPosterDuan.size();m++) {
                            Wall.get(j).add(k,newPosterDuan.get(m));
                        }
                    }
                }
            }
            ArrayList<Node> temp =new ArrayList<Node>();//加入新海报
            temp.add(arr.get(i));
            Wall.add(temp);
        }
        //求总的不为空的海报数量
        int count = 0;
        for(int i=0;i<Wall.size();i++) {
            boolean flag = false;
            ArrayList<Node> temp = Wall.get(i);
            for(int k=0;k<temp.size();k++) {
                if(temp.get(k)!=null) {
                    flag = true;
                }
            }
            if(flag==true) {
                count++;
            }
        }
        System.out.println(count);
    }
    public static ArrayList<Node> Overlap(Node node1,Node node2) {//求node1的补集
        ArrayList<Node> newPosterDuan = new ArrayList<Node>();
        if(node1==null) {
            return null;
        }
        if(node1.left>=node2.left && node1.right<=node2.right ) {
            return null;
        }
        else if(node1.left<=node2.left && node1.right<=node2.right && 
                node2.left<=node1.right) {
            node1.right = node2.left;
            if(node1.left!=node1.right) {
                newPosterDuan.add(node1);	
            }
        }else if(node1.left<=node2.right&&node1.left>=node2.left&&
                 node1.right>=node2.right) {
            node1.left = node2.right;
            if(node1.left!=node1.right) {
                newPosterDuan.add(node1);	
            }
        }else if(node1.left<=node2.left&&node1.right>=node2.right) {
            Node newNode1 = new Node(node1.left,node2.left);
            Node newNode2 = new Node(node2.right,node1.right);
            if(node1.left!=node1.right) {
                newPosterDuan.add(newNode1);	
            }
            if(node2.left!=node2.right) {
                newPosterDuan.add(newNode2);	
            }
        }else {
            newPosterDuan.add(node1);
        }
        return newPosterDuan;
    }
}
class Node{
    int left;
    int right;
    public Node(int left,int right) {
        this.left = left;
        this.right = right;
    }
    @Override
    public String toString() {
        return "Node [left=" + left + ", right=" + right + "]";
    }
}

发表于 2020-04-08 14:36:09 回复(1)
// 正确率100%
//区间覆盖问题:存储当前每张未被覆盖海报的覆盖范围,对新海报查询左右边界,删除被覆盖海报,整个过程可以用set维护,时间复杂度O(NlogN)
#include <bits/stdc++.h>
using namespace std;

struct poster {
    int l, r, id; // id为海报标识
    // set比较函数后必须加const
    bool operator<(const poster &b) const {
        return l < b.l;
    }
};
set<poster> s;
set<poster>::iterator it1, it2;

int main() {
    int n;
    while (~scanf("%d", &n)) {
        int a, b;
        scanf("%d%d", &a, &b);
        s.insert({a, b, 0});
        for (int i = 1; i < n; i++) {
            scanf("%d%d", &a, &b);
            // 查询左右边界
            it1 = s.upper_bound({a, 0, 0});
            it2 = s.upper_bound({b, 0, 0});
            if (it1 == s.begin()) { //位于所有海报前面
                if (it2 == s.begin()) {
                    s.insert({a, b, i});
                } else {
                    it2--;
                    int r = it2->r, id = it2->id;
                    s.erase(it1, ++it2);
                    s.insert({a, b, i});
                    s.insert({b, r, id});
                }
            } else {
                it1--; it2--;
                int l = it1->l, r = it2->r, id1 = it1->id, id2 = it2->id;
                s.erase(it1, ++it2);
                if (r <= a) { // 位于所有海报后面
                    s.insert({l, r, id1});
                    s.insert({a, b, i});
                } else { //位于海报中间
                    if(l < a) s.insert({l, a, id1});
                    s.insert({a, b, i});
                    if (r > b) s.insert({b, r, id2});
                }
            }
        }
        unordered_set<int> hs;
        int ans = 0;
        for (it1 = s.begin(); it1 != s.end(); it1++) {
            if (hs.find(it1->id) == hs.end()) {
                ans++;
                hs.insert(it1->id);
            }
        }
        s.clear();
        printf("%d\n", ans);
    }
    return 0;
}


发表于 2020-04-08 01:52:23 回复(0)
python解 ac 80% 运行超时
给每个单位区间段一个编号,海报覆盖就相当于重叠,重新赋值一段海报长度的一样的编号
请大佬帮忙看看有无解决办法
import sys
n=int(input())
data=[]
for i in range(n):
    data.append(list(map(int,sys.stdin.readline().strip().split())))
res=[0]*10000000#给每个单位区间段一个编号,海报覆盖就相当于重叠,重新赋值一段海报长度的一样的编号
for i in range(1,n+1):
    res[data[i-1][0]:data[i-1][1]]=[i]*(data[i-1][1]-data[i-1][0])
res=set(res)
ress=len(res)-1
print(ress)


发表于 2020-03-26 15:24:36 回复(0)
#include<iostream>
#include<set>
#include<algorithm>
#include<vector>
using namespace std;
int main(){
    int n,left,right,res=0;
    cin>>n;
    vector<pair<int,int>> hb;
    set<pair<int,int>> tmp;
    for(int i=0;i<n;i++){
        cin>>left>>right;
        hb.push_back(make_pair(left,right));
    }
    tmp.insert(hb[n-1]);
    res++;
    set<pair<int,int>>::iterator iter;
    for(int i=n-2;i>=0;i--){
        iter=tmp.begin();
        if(iter->first>=hb[i].second){
            if(iter->first==hb[i].second){
                hb[i].second=iter->second;
                tmp.erase(iter);
                tmp.insert(hb[i]);
            }else
                tmp.insert(hb[i]);
            res++;
            continue;
        }
        while(iter!=tmp.end()&&hb[i].first>iter->second){
            iter++;
        }
        if(iter==tmp.end()){
            tmp.insert(hb[i]);
            res++;
            continue;
        }
        if(hb[i].first>=iter->first&&hb[i].second<=iter->second)
            continue;
        if(hb[i].second<iter->first){
            tmp.insert(hb[i]);
            res++;
            continue;
        }
        pair<int,int> ni;
        res++;
        ni.first=min(iter->first,hb[i].first);
        ni.second=max(iter->second,hb[i].second);
        set<pair<int,int>>::iterator iter2=iter;
        iter2++;
        while(iter2!=tmp.end()&&iter2->first<=ni.second){
            ni.second=max(ni.second,iter2->second);
            tmp.erase(iter2);
            iter2=iter;
            iter2++;
        }
        tmp.erase(iter);
        tmp.insert(ni);
    }
    if(n==0)
        cout<<0<<endl;
    else
        cout<<res<<endl;
    return 0;
}
从最后一张海报开始计算已被覆盖的区域,使用set<pair<int,int>> 保存确定会被显露的区域
(由于是从后向前,所以先被记录的区间实际是后贴的,最后一定会显露出来)。
每贴一张海报(从后向前),与确定会被显露的海报区间比较:
(1)如被包含,则这张海报不会被看到
(2)如与确定会被显露的海报没有交集,则该海报最后也会被显露。
(3)如与确定会被显露的海报有交集且没有完全被覆盖,则合并区间。

代码中各种状况整理的的不是很好,但所有测试用例都能通过。
编辑于 2020-02-29 16:13:58 回复(0)
//#include "utils.cpp"
#include <bits/stdc++.h>
using namespace std;


vector<int> li,ri;
int N;
//求[l,r]被k以后海报遮掩的情况
bool f(int l,int r,int k){
    if(k==N) return false;
	//1.两者无交集
	if(li[k]>=r&nbs***bsp;ri[k]<=l) return f(l,r,k+1);
    //2.被完全遮掩
    if(li[k]<=l and ri[k]>=r) return true;
    //3.左半边被完全遮掩
    if(li[k]<=l and ri[k]<r) return f(ri[k],r,k+1);
    //4.右半边被完全遮掩
    if(ri[k]>=r and li[k]>l) return f(l,li[k],k+1);
    //5.中间一部分被遮掩
    if(li[k]>l and ri[k]<r){
		//PR(f(l,li[k],k+1) , f(ri[k],r,k+1));
        return f(l,li[k],k+1) && f(ri[k],r,k+1);
    }
    
    
}

int main(){
	//freopen("temp.in","r",stdin);
    cin>>N;
    li.resize(N);
    ri.resize(N);
    for(int i=0;i<N;i++){
        cin>>li[i]>>ri[i];
    }
    int ans = 0;
    for(int i=0;i<N;i++){
        if(f(li[i],ri[i],i+1)) continue;
        ans++;
    }
    cout<<ans<<endl;
    return 0;
}

发表于 2020-02-16 10:05:34 回复(0)
#include<iostream>
#include<vector>
using namespace std;
int main()
{
    int n;
    cin>>n;
    vector<pair<int,int>> m;
    int s,t;
    while(n)
    {
        cin>>s>>t;
        n--;
        m.push_back(make_pair(s,t));
    }
    for(auto it=m.begin();it!=m.end();it++)
    {
        auto ot=it;
        ot++;
        for(;ot!=m.end();ot++)
        {
            if((ot->first<it->second)&&(ot->second>=it->second))
                it->second=ot->first;
            else if((ot->second>it->first)&&(ot->first<=it->first))
                it->first=ot->second;
           // else if((ot->first>it->first)&&(ot->second<it->second))
           // {
                
            //}
        }
    }
    int sum=0;
    for(auto it:m)
    {
        if(it.first<=it.second)
            sum++;
    }
    cout<<sum;
}

发表于 2020-02-11 15:31:46 回复(0)