4237: 稻草人

4237: 稻草人

https://www.lydsy.com/JudgeOnline/problem.php?id=4237

分析:

  CDQ分治+单调栈。

  首先按照x排序,每次分治,考虑左边对右边的贡献。CDQ的过程中,按照y从大到小排序。

  

代码:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<iostream>
 6 #include<cctype>
 7 #include<set>
 8 #include<vector>
 9 #include<queue>
10 #include<map>
11 #include<stack>
12 #define fi(s) freopen(s,"r",stdin);
13 #define fo(s) freopen(s,"w",stdout);
14 using namespace std;
15 typedef long long LL;
16
17 inline int read() {
18     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch==‘-‘)f=-1;
19     for(;isdigit(ch);ch=getchar())x=x*10+ch-‘0‘;return x*f;
20 }
21
22 const int N = 200005;
23
24 int n;
25 struct Node{
26     int x, y;
27     Node() {}
28     Node(int _x,int _y) { x = _x, y = _y; }
29 }A[N], B[N], sk1[N], sk2[N];
30 int top1, top2;
31 LL Ans;
32
33 bool operator < (const Node &A, const Node &B) {
34     return A.x < B.x;
35 }
36
37 int find(int k) {
38     int L = 1, R = top2 + 1, res = top2 + 1;
39     while (L <= R) {
40         int mid = (L + R) >> 1;
41         if (sk2[mid].y < k) res = mid, R = mid - 1; // sk中y是递减的
42         else L = mid + 1;
43     }
44     return res;
45 }
46
47 void CDQ(int l,int r) {
48     if (l >= r) return ;
49     int mid = (l + r) >> 1;
50     CDQ(l, mid); CDQ(mid + 1, r);
51
52     top1 = 0, top2 = 0;
53     int i = l, j = mid + 1, k;
54     for (i=l; i<=mid; ++i) {
55         while (top1 && sk1[top1].x < A[i].x) top1--; // x单调递减
56         sk1[++top1] = A[i];
57         while (j<=r && A[j].y >= A[i].y) {
58             while (top2 && sk2[top2].x > A[j].x) top2 --; // x单调递增
59             sk2[++top2] = A[j ++];
60         }
61         if (top1 == 1) Ans += top2;
62         else Ans += top2 - find(sk1[top1-1].y) + 1;
63     }
64     i = l, j = mid + 1, k = l;
65     while (i <= mid && j <= r) {
66         if (A[i].y > A[j].y) B[k++] = A[i ++];
67         else B[k++] = A[j ++];
68     }
69     while (i <= mid) B[k ++] = A[i ++];
70     while (j <= r) B[k ++] = A[j ++];
71     for (i=l; i<=r; ++i) A[i] = B[i];
72 }
73
74 int main() {
75     n = read();
76     for (int i=1; i<=n; ++i) {
77         int x = read(), y = read();
78         A[i] = Node(x, y);
79     }
80     sort(A + 1, A + n + 1);
81     CDQ(1, n);
82     cout << Ans;
83     return 0;
84 }

原文地址:https://www.cnblogs.com/mjtcn/p/9716078.html

时间: 2024-11-09 04:56:53

4237: 稻草人的相关文章

BZOJ 4237: 稻草人

4237: 稻草人 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 661  Solved: 286[Submit][Status][Discuss] Description JOI村有一片荒地,上面竖着N个稻草人,村民们每年多次在稻草人们的周围举行祭典. 有一次,JOI村的村长听到了稻草人们的启示,计划在荒地中开垦一片田地.和启示中的一样,田地需要满足以下条件: 田地的形状是边平行于坐标轴的长方形: 左下角和右上角各有一个稻草人: 田地的内部(不

bzoj 4237: 稻草人 -- CDQ分治

4237: 稻草人 Time Limit: 40 Sec  Memory Limit: 256 MB Description JOI村有一片荒地,上面竖着N个稻草人,村民们每年多次在稻草人们的周围举行祭典. 有一次,JOI村的村长听到了稻草人们的启示,计划在荒地中开垦一片田地.和启示中的一样,田地需要满足以下条件: 田地的形状是边平行于坐标轴的长方形: 左下角和右上角各有一个稻草人: 田地的内部(不包括边界)没有稻草人. 给出每个稻草人的坐标,请你求出有多少遵从启示的田地的个数 Input 第一

BZOJ 4236~4247 题解

BZOJ 4236 JOIOJI f[i][0..2]表示前i个字符中′J′/′O′/′I′的个数 将二元组<f[i][0]?f[i][1],f[i][1]?f[i][2]>扔进map,记录一下最早出现的时间 对于每个位置去map里面查一下即可 时间复杂度O(nlogn) #include <map> #include <cstdio> #include <cstring> #include <iostream> #include <alg

《巨婴国》:差评。伪科学/非科学,逻辑比较差,以偏概全,解释牵强,竖起一个稻草人打得挺嗨。1星

读后感觉比较差.只能给1星.相当于负分的水平. 作者认为中国人大部分是没长大的婴儿,不能正确处理人际关系,隐含地推论常见的心理疾病.变态人格.不正常情商都是巨婴病的表现,明确地推论巨婴理论可以解释许多世界历史和国际政治上的事情. 差评理由有下面几个: 1:“巨婴国”的学说到底是不是一个严肃的学术上的推论?我认为不是.我认为可以归入伪科学或非科学的范畴.作者虽然是北大心理学系的本科和硕士毕业,但是全书是浓郁的江湖派的风格.作者提到了一个惊世骇俗的“巨婴学说”,并且断定中国人大部分是“巨婴”,因此中

时代的稻草人

叶圣陶老先生写过一篇童话<稻草人>:稻草人"骨架子是竹园里的细竹枝,肌肉.皮肤是隔年的黄稻草,拿着一把破扇子".稻草人尽职尽责.心地善良,但面对现实却无能为力.他爱他的主人,却不能赶走田里的害虫给主人带来好收成,他帮不了生病的孩子.频死的鲫鱼和寻死的女人--许知远的<时代的稻草人>引用了这个童话,并表达了知识分子在这个时代面前深深的无力感. <稻草人>写于1922年,正值五四运动后新思想与旧观念的激烈冲突之时,"在历史的惯性与现实面前,新思

bzoj4237 稻草人

Description JOI村有一片荒地,上面竖着N个稻草人,村民们每年多次在稻草人们的周围举行祭典. 有一次,JOI村的村长听到了稻草人们的启示,计划在荒地中开垦一片田地.和启示中的一样,田地需要满足以下条件: 田地的形状是边平行于坐标轴的长方形: 左下角和右上角各有一个稻草人: 田地的内部(不包括边界)没有稻草人. 给出每个稻草人的坐标,请你求出有多少遵从启示的田地的个数 Input 第一行一个正整数N,代表稻草人的个数 接下来N行,第i行(1<=i<=N)包含2个由空格分隔的整数Xi和

HDU4462稻草人

l问题描述:有一块N*N的玉米田(N<=50),给定K个(X,Y)的坐标位置(K<=10)和相应的覆盖范围,请问,至少在这K个位置中选择几个放置稻草人,能保证玉米田全被覆盖? 1 #include<stdio.h> 2 #include<cstring> 3 #include<iostream> 4 5 using namespace std; 6 7 int field[52][52]; 8 int N,K; 9 10 struct Node{ 11 in

bzoj4237稻草人

题意:给你一个田地,问左下角和右上角有稻草人并且内部除了边界都没有稻草人的矩形数. 标程: 1 #include<bits/stdc++.h> 2 using namespace std; 3 int read() 4 { 5 int x=0,f=1;char ch=getchar(); 6 while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();} 7 while (ch>='0'&&ch<='9'

bzoj4237 稻草人——分治

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4237 分治: 先把所有点按 y 排序,然后二分递归: 对于每个 mid ,计算经过它的矩形的个数,把上面的每个点当做右上角,考虑下面多少点可以作为左下角: 上面的限制只有前面的 y 大于等于自己的 y,所以维护递增的单调栈: 下面的限制是后面的 y 小于等于自己的 y,所以维护递减的单调栈: 还要注意 x 的限制,二分找到栈内满足条件的最前面的点,到栈顶的元素个数就是对答案的贡献. 代码如