[CF989D]A Shade of Moonlight:几何+二分答案+玄学的思路

题意:

一条一维数轴上,有n个左端点为xi,长度l的区间。以向右为正方向,第i个区间的移动速度为vi+w(vi=1或-1,|w|<=wmax,所有区间的w相同)。

输入n,l,wmax,vi。

输出无序数对(i,j)的个数,使第i个区间和第j个区间有一个合法的w的取值,在某一时刻同时覆盖原点(不包括区间左、右边界)。

(n<=1e5)

思路:

因为w的取值是不定的,所以可以看成是每个区间以vi的速度运动,而原点以-w的速度运动。

很容易画出一个时间-位置图像(横轴位置,纵轴时间),其中橙色区域为原点在对应时间可能的位置。

可以发现,只要第i个和第j个区间所相交形成的斜正方形与橙色区域有公共部分,则说明(i,j)是我们要求的一个无序数对。

很显然只要考虑斜正方形最上面的顶点即可。

那么可以将v=1和v=-1的区间分开,给v=-1的区间排序。

然后对每一个v=1的区间二分查找一个x最小的v=-1的区间,使其相交的斜正方形区域与橙色区域有交集,统计答案即可。

完了。

记得开long long。

代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <cmath>
 6 #include <algorithm>
 7 using namespace std;
 8 typedef long long LL;
 9 int read(){
10     int x=0,f=1;char ch=getchar();
11     while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
12     while(ch>=‘0‘&&ch<=‘9‘){x=(x<<3)+(x<<1)+ch-‘0‘;ch=getchar();}
13     return x*f;
14 }
15 const int SIZE=100005;
16 int n,l,w,ans,ch;
17 int lf[SIZE],rt[SIZE],lnt,rnt;
18 bool check(int mid){
19     mid=lf[mid]+l;
20     double h=(double)(mid-ch)/2;//斜正方形最上面的顶点的纵坐标。
21     if(h>fabs((double)(mid+ch)/(2.0*w))) return 1;
22     else return 0;
23 }
24 void bisearch(int l,int r){
25     if(l>r) return;
26     int mid=((l+r)>>1);
27     if(check(mid)){
28         ans=mid;
29         bisearch(mid+1,r);
30     }
31     else bisearch(l,mid-1);
32 }
33 bool cmp(int x,int y){
34     return x>y;
35 }
36 int main(){
37     n=read(),l=read(),w=read();
38     for(int i=1;i<=n;i++){
39         int x=read(),v=read();
40         if(v==1) rt[++rnt]=x;
41         else lf[++lnt]=x;
42     }
43     sort(lf+1,lf+lnt+1,cmp);
44     LL rez=0;
45     for(int i=1;i<=rnt;i++){
46         ans=0;
47         ch=rt[i];//ch存当前正在查询的v=1的区间的左边界。
48         bisearch(1,lnt);
49         rez+=ans;
50     }
51     printf("%I64d\n",rez);
52     return 0;
53 }

原文地址:https://www.cnblogs.com/KuriyamaMirai/p/9196796.html

时间: 2024-08-02 04:52:24

[CF989D]A Shade of Moonlight:几何+二分答案+玄学的思路的相关文章

Codeforces 989D A Shade of Moonlight

A Shade of Moonlight 列列式子发现, 对于同一个云来说只有反向的云才能和它相交, 然后我们发现这个东西有单调性,然后二分就好啦. #include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define PLL pair<LL, LL> #define PLI pair<LL, int> #define PI

Codeforces 772A Voltage Keepsake - 二分答案

You have n devices that you want to use simultaneously. The i-th device uses ai units of power per second. This usage is continuous. That is, in λ seconds, the device will use λ·ai units of power. The i-th device currently has bi units of power store

HDU3081Marriage Match II(二分答案+并查集+最大流SAP)经典

Marriage Match II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2507    Accepted Submission(s): 856 Problem Description Presumably, you all have known the question of stable marriage match. A

Codeforce 371C Hamburgers (二分答案)

题目链接 Hamburgers 二分答案,贪心判断即可. 1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define REP(i,n) for(int i(0); i < (n); ++i) 6 #define LL long long 7 8 char str[1010]; 9 LL len; 10 LL b, c, s, nb, nc, ns, pb, pc, ps; 11 LL money; 12 13 bool

POJ 3080 Blue Jeans(后缀数组+二分答案)

[题目链接] http://poj.org/problem?id=3080 [题目大意] 求k个串的最长公共子串,如果存在多个则输出字典序最小,如果长度小于3则判断查找失败. [题解] 将所有字符串通过拼接符拼成一个串,做一遍后缀数组,二分答案,对于二分所得值,将h数组大于这个值的相邻元素分为一组,判断组内元素是否覆盖全字典,是则答案成立,对于答案扫描sa,输出第一个扫描到的子串即可. [代码] #include <cstdio> #include <cstring> #inclu

【二分答案+智障的字符串hash】BZOJ2946-[Poi2000]公共串(Ranklist倒一达成!!!!!)【含hash知识点】

[题目大意] 给出几个由小写字母构成的单词,求它们最长的公共子串的长度. [字符串hash的小笔记] hash[i]=(hash[i-1]*p+idx(s[i]))%mod,idx为映射值,一般a..z映射1..26: 习惯上,p取一个6到8位的素数即可,mod一般取大素数 1e9+7(1000000007)或1e9+9(1000000009). hash[i]=(hash[i-1]*p+idx(s[i]))%mod 表示第 i 个前缀的hash值,是一个hash的前缀和,那么,要求S[l…r]

IndiaHacks 2016 - Online Edition (Div. 1 + Div. 2) 二分答案 + 网络流

这道题的意思是给你一个有向图, 每条边上有一个最大载重量, 现在有x头牛要从顶点1走向顶点n, 每头牛要载的重量都是一样的, 问你最多能载多少的重量? 可以二分答案, 算出每头牛的载重, 然后修改边权, 跑一次最大流即可判断当前答案是否正确, 二分答案即可, 注意由于原始边权/每头牛的载重量可能会很大, 因此我们在修改边权时应该注意这一点,将边权的最大值控制在1000000之内, 防止溢出, 代码如下: #include <bits/stdc++.h> using namespace std;

BZOJ 1305 CQOI2009 dance跳舞 二分答案+最大流

题目大意:给定n个男生和n个女生,一些互相喜欢而一些不.举行几次舞会,每次舞会要配成n对.不能有同样的组合出现.每一个人仅仅能与不喜欢的人跳k次舞,求最多举行几次舞会 将一个人拆成两个点.点1向点2连一条流量为k的边.两个人若互相喜欢则点1之间连边,不喜欢则点2之间连边 对于每个要验证的x值 将每个人的点1向源或汇连一条流量为x的边 然后二分答案跑最大流就可以 #include<cstdio> #include<cstring> #include<iostream> #

Educational Codeforces Round 3:D. Gadgets for dollars and pounds(二分答案+贪心)

看了菊苣的理解才知道怎么写..根本没思路啊一开始... 天数肯定在1~n之间,二分答案. 可以用保存前i天的最低美元和英镑汇率,没有规定哪天买,每天也没有购买数量限制,所以二分出一个答案mid的后,就在前mid天中汇率最低的时候一次性购入最便宜的就行了,judge一下总花费 打印答案的时候以ans为结果,再模拟一遍就好 #include"cstdio" #include"queue" #include"cmath" #include"s