UOJ276 [清华集训2016] 汽水 【二分答案】【点分治】【树状数组】

题目分析:

这种乱七八糟的题目一看就是点分治,答案有单调性,所以还可以二分答案。

我们每次二分的时候考虑答案会不会大于等于某个值,注意到系数$k$是无意义的,因为我们可以通过转化使得$k=0$。

合并的过程相当于很多个向量,加起来后看斜率。

注意单个向量也要判定。

由于有了二分的答案$Ans$。判定变得简单多了,推一下。

$-k \leq \frac{A+C}{B+D} \leq k \Rightarrow -k(B+D) \leq A+C \leq k(B+D)$.

进一步的$A+kB \geq -C-kD$且$A-kB \leq kD-C$。虽然有四元,但是顺序相互关联,所以实际只有两元,排序后树状数组就可以解决啦。

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3
  4 typedef long long ll;
  5
  6 const int maxn = 50100;
  7
  8 ll k,md; int flag = 0,num,n,rnum;
  9 vector <pair<int,ll> > g[maxn];
 10 int arr[maxn],sz[maxn],imp[maxn],cnt[maxn];
 11 struct node{ll A;int B,pla;}op[maxn];
 12
 13 int cmp(node X,node Y){
 14     return -X.A-md*X.B < -Y.A-md*Y.B;
 15 }
 16
 17 struct Fenwick{
 18     int C[maxn];
 19     void Add(int now){
 20     while(now <= rnum){C[now] ++; now += (now&-now);}
 21     }
 22     int query(int now){
 23     int ans = 0;
 24     while(now){ans += C[now]; now -= (now&-now);}
 25     return ans;
 26     }
 27 }T1;
 28
 29 void read(){
 30     scanf("%d%lld",&n,&k);
 31     for(int i=1;i<n;i++){
 32     int x,y;long long v; scanf("%d%d%lld",&x,&y,&v); v -= k;
 33     g[x].push_back(make_pair(y,v)); g[y].push_back(make_pair(x,v));
 34     }
 35 }
 36
 37 void dfs1(int now,int fa,int dp){
 38     sz[now] = 1;imp[now] = 0;
 39     for(auto it : g[now]){
 40     if((arr[it.first] && arr[it.first] < dp) || fa == it.first) continue;
 41     dfs1(it.first,now,dp); sz[now] += sz[it.first];
 42     }
 43 }
 44
 45 int dfs2(int now,int fa,int dp,int ssz){
 46     int ans = 0;
 47     for(auto it : g[now]){
 48     if((arr[it.first] && arr[it.first] < dp) || fa == it.first) continue;
 49     int data = dfs2(it.first,now,dp,ssz);
 50     if(ans==0 || imp[ans] > imp[data])ans = data;
 51     imp[now] = max(sz[it.first],imp[now]);
 52     }
 53     imp[now] = max(imp[now],ssz-sz[now]);
 54     if(ans==0 || imp[ans] > imp[now]) ans = now;
 55     return ans;
 56 }
 57
 58 void dfs3(int now,int fa,int dp,int A,int B){
 59     for(auto it : g[now]){
 60     if(it.first == fa || (arr[it.first] && arr[it.first] < dp)) continue;
 61     op[++num] = (node){A+it.second,B+1,it.first};
 62     dfs3(it.first,now,dp,A+it.second,B+1);
 63     }
 64 }
 65
 66 long long lisan[maxn];
 67 void solve(int dr){
 68     rnum = num;
 69     for(int i=1;i<=num;i++){lisan[i] = -op[i].A+md*op[i].B;}
 70     sort(lisan+1,lisan+num+1);rnum = unique(lisan+1,lisan+num+1)-lisan-1;
 71     for(int i=1;i<=rnum;i++) T1.C[i]=0;
 72     for(int i=num,j=1;i>=1;i--){
 73     while(j <= num && (-op[j].A-md*op[j].B < op[i].A+md*op[i].B)){
 74         T1.Add(lower_bound(lisan+1,lisan+rnum+1,-op[j].A+md*op[j].B)-lisan);
 75         j++;
 76     }
 77     int ans=j-1-T1.query(upper_bound(lisan+1,lisan+rnum+1,op[i].A-md*op[i].B)-lisan-1);
 78     if(op[i].A-md*op[i].B < -op[i].A+md*op[i].B && j > i)ans--;
 79     if(dr == 1){
 80         if(ans - cnt[op[i].pla]){flag = 1;return;}
 81     }else{cnt[op[i].pla] = ans;}
 82     }
 83 }
 84
 85 void divide(int now,int dp,int lst,long long AA){
 86     dfs1(now,0,dp); int heavy = dfs2(now,0,dp,sz[now]);arr[heavy] = dp;
 87     for(auto it : g[heavy]){
 88     if(arr[it.first]&&arr[it.first]<dp) continue;
 89     divide(it.first,dp+1,heavy,it.second);
 90     if(flag == 1) return;
 91     }
 92     num = 0; dfs3(heavy,0,dp,0,0); sort(op+1,op+num+1,cmp);
 93     solve(1); num = 0;
 94     if(lst) {
 95     num = 0;dfs3(now,0,dp,AA,1);
 96     sort(op+1,op+num+1,cmp);
 97     for(int i=1;i<=num;i++) cnt[op[i].pla] = 0;
 98     solve(0);
 99     }
100 }
101
102 void work(){
103     long long l = 0,r = 1e13;
104     while(l < r){
105     md = (l+r)/2; flag = 0;
106     memset(arr,0,sizeof(arr));
107     divide(1,1,0,0);
108     if(flag) r = md; else l = md+1;
109     }
110     printf("%lld",l-1);
111 }
112
113 int main(){
114     read();
115     work();
116     return 0;
117 }

原文地址:https://www.cnblogs.com/Menhera/p/9347630.html

时间: 2024-08-01 20:56:16

UOJ276 [清华集训2016] 汽水 【二分答案】【点分治】【树状数组】的相关文章

csp-s模拟测试56(10.2)Merchant「二分」&#183;Equation「树状数组」

又死了......T1 Merchant 因为每个集合都可以写成一次函数的形式,所以假设是单调升的函数,那么随着t越大就越佳 而单调减的函数,随着t的增大结果越小,所以不是单调的??? 但是我们的单调只需凭借t时刻的sum值是否大于S即可 如果某个单减的集合符合情况,那么他在t==0时就符合情况 如果不符合,那么他就不会作出贡献 所以可以二分 T2 Equation 一开始以为是高斯消元??? 当然不是..... 把每个xi均用x1表示,那么我们发现,对于深度奇偶不同的点,他的表示方式是不同的,

【UOJ274】【清华集训2016】温暖会指引我们前行 LCT

[UOJ274][清华集训2016]温暖会指引我们前行 任务描述 虽然小R住的宿舍楼早已来了暖气,但是由于某些原因,宿舍楼中的某些窗户仍然开着(例如厕所的窗户),这就使得宿舍楼中有一些路上的温度还是很低. 小R的宿舍楼中有n个地点和一些路,一条路连接了两个地点,小R可以通过这条路从其中任意一个地点到达另外一个地点.但在刚开始,小R还不熟悉宿舍楼中的任何一条路,所以他会慢慢地发现这些路,他在发现一条路时还会知道这条路的温度和长度.每条路的温度都是互不相同的. 小R需要在宿舍楼中活动,每次他都需要从

bzoj 4736 /uoj274【清华集训2016】温暖会指引我们前行 lct

[清华集训2016]温暖会指引我们前行 统计 描述 提交 自定义测试 寒冬又一次肆虐了北国大地 无情的北风穿透了人们御寒的衣物 可怜虫们在冬夜中发出无助的哀嚎 “冻死宝宝了!” 这时 远处的天边出现了一位火焰之神 “我将赐予你们温暖和希望!” 只见他的身体中喷射出火焰之力 通过坚固的钢铁,传遍了千家万户 这时,只听见人们欢呼 “暖气来啦!” 任务描述 虽然小R住的宿舍楼早已来了暖气,但是由于某些原因,宿舍楼中的某些窗户仍然开着(例如厕所的窗户),这就使得宿舍楼中有一些路上的温度还是很低. 小R的

4418: [Shoi2013]扇形面积并|二分答案|树状数组

为何感觉SHOI的题好水...又是一道SB题 从左到右枚举每一个区间,遇到一个扇形的左区间就+1,遇到右区间就-1,然后再树状数组上2分答案,还是不会码log的..SHOI2013似乎还有一道题发牌也是类似的维护方法.. #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<vector>

[清华集训2017]小 Y 和地铁(神奇思路,搜索,剪枝,树状数组)

世界上最不缺的就是好题. 首先考虑暴搜.(还有什么题是从这东西推到正解的……) 首先单独一个换乘站明显没用,只用考虑一对对的换乘站. 那么有八种情况:(从题解偷图)         然后大力枚举每个换乘站的情况.同时判断交点.$O(n\times 8^{\frac{n}{2}})$. 然后考虑这种情况: 发现对于任意一条地铁线,要么与这两个都有交点,要么可以与这两个都没有交点.(其实会有与一个有两个交点,与另一个没有交点的情况.这时也可以把这条线换个方向,答案不会更差.思考思考为什么) 那么合法

BZOJ 2738 矩阵乘法(整体二分+二维树状数组)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2738 [题目大意] 给出一个方格图,询问要求求出矩阵内第k小的元素 [题解] 我们对答案的大小进行整体二分,用二维树状数组维护二维区间和, 将超过数量的分治到左区间,不满足的分治到右区间即可. [代码] #include <cstdio> #include <algorithm> #include <cstring> using namespace std;

【bzoj2527】[Poi2011]Meteors 整体二分+树状数组

题目描述 有N个成员国.现在它发现了一颗新的星球,这颗星球的轨道被分为M份(第M份和第1份相邻),第i份上有第Ai个国家的太空站. 这个星球经常会下陨石雨.BIU已经预测了接下来K场陨石雨的情况.BIU的第i个成员国希望能够收集Pi单位的陨石样本.你的任务是判断对于每个国家,它需要在第几次陨石雨之后,才能收集足够的陨石. 输入 第一行是两个数N,M. 第二行有M个数,第i个数Oi表示第i段轨道上有第Oi个国家的太空站. 第三行有N个数,第i个数Pi表示第i个国家希望收集的陨石数量. 第四行有一个

【51nod】 第K大区间2(二分+树状数组)

[51nod] 第K大区间2(二分+树状数组) 第K大区间2 ﹡    LH (命题人) 基准时间限制:1.5 秒 空间限制:131072 KB 分值: 160 定义一个长度为奇数的区间的值为其所包含的的元素的中位数.中位数_百度百科 现给出n个数,求将所有长度为奇数的区间的值排序后,第K大的值为多少. 样例解释: [l,r]表示区间的值 [1]:3 [2]:1 [3]:2 [4]:4 [1,3]:2 [2,4]:2 第三大是2 Input 第一行两个数n和k(1<=n<=100000,k&l

bzoj 2527 Meteors - 整体二分 - 树状数组

Description Byteotian Interstellar Union (BIU) has recently discovered a new planet in a nearby galaxy. The planet is unsuitable for colonisation due to strange meteor showers, which on the other hand make it an exceptionally interesting object of st