我们部门需要装饰墙,但是墙非常非常的长,有一千万米。我们会按顺序贴很多海报在上面,这些海报相互之间会重叠,请问下,最后还能看到哪些?(只看到一部分也算)
N表示N张海报
接下来每一行代表海报的左右边界(上下默认全满),Li,Ri,均为整数,大于0,小于一千万。海报按输入顺序张贴。
有多少张海报是可见的
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;
}
#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;
} #优化过的顺序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() https://blog.csdn.net/FlushHip/article/details/84137906
我感觉数据有误
#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;
}
#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;
} #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();
} 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());
}
} 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());
}
} 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;
}
#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;
}
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 + "]";
}
} #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;
} 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)
#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;
}
//#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;
} #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;
}