[CodeChef - STREETTA] The Street 李超线段树

  大致题意:

    给出两个序列A,B,A初始为负无穷,B初始为0,有三种操作

    1、在A上区间[u,v]上加一个等差数列,取与原本A序列的最大值。

    2、在B上区间[u,v]上加一个等差数列。

    3、给出一个点X,询问A[X]+B[X]的值。

    学习一个李超线段树就ojbk了,对于每次加入的等差数列,可以转化为y=a*i+b的一条线段,用李超线段树维护所有线段

    所覆盖的区间即可。数据范围比较大,线段树可以动态开点,也可以离散化。

    

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<queue>
  6 #include<set>
  7 #include<map>
  8 #include<stack>
  9 #include<time.h>
 10 #include<cstdlib>
 11 #include<cmath>
 12 #include<list>
 13 using namespace std;
 14 #define MAXN 10000006
 15 #define eps 1e-8
 16 #define For(i,a,b) for(int i=a;i<=b;i++)
 17 #define Fore(i,a,b) for(int i=a;i>=b;i--)
 18 #define lson l,mid
 19 #define rson mid+1,r
 20 #define mkp make_pair
 21 #define pb push_back
 22 #define cr clear()
 23 #define sz size()
 24 #define met(a,b) memset(a,b,sizeof(a))
 25 #define iossy ios::sync_with_stdio(false)
 26 #define fr freopen
 27 #define pi acos(-1.0)
 28 #define Vector Point
 29 #define fir first
 30 #define sec second
 31 const long long inf=1LL<<62;
 32 const int Mod=1e9+7;
 33 typedef unsigned long long ull;
 34 typedef long long ll;
 35 typedef pair<int,int> pii;
 36 typedef pair<ll,ll> pll;
 37 inline int scan(){
 38     int x=0,f=1;char ch=getchar();
 39     while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
 40     while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
 41     return x*f;
 42 }
 43 struct LcSegmentTree{
 44     ll k,b,sk,sb;
 45     int mk;
 46     int ls,rs;
 47 };
 48 ll ans1,ans2;
 49 LcSegmentTree t[MAXN];
 50 int tot=0;
 51 void seg1_change(int L,int R,ll a,ll b,int l,int r,int &rt){
 52     if(!rt) {
 53         rt=++tot;
 54         t[rt].k=0;
 55         t[rt].b=-inf;
 56     }
 57     //cout<<L<<" "<<R<<" "<<a<<" "<<b<<" "<<l<<" "<<r<<" "<<rt<<" "<<t[rt].mk<<" "<<t[rt].k<<" "<<t[rt].b<<endl;
 58     if(L==l && R==r){
 59         bool f1=(t[rt].k*l+t[rt].b>=a*l+b),f2=(t[rt].k*r+t[rt].b>=a*r+b);
 60         if(f1&&f2) return ;
 61         if(!f1 && !f2) {t[rt].k=a,t[rt].b=b;return ;}
 62         int mid=l+r>>1;
 63         bool fm=t[rt].k*mid+t[rt].b>=a*mid+b;
 64         if(f1){
 65             if(fm) seg1_change(mid+1,R,a,b,rson,t[rt].rs);
 66             else {
 67                 seg1_change(L,mid,t[rt].k,t[rt].b,lson,t[rt].ls);
 68                 t[rt].k=a;
 69                 t[rt].b=b;
 70             }
 71         }else{
 72             if(fm) seg1_change(L,mid,a,b,lson,t[rt].ls);
 73             else {
 74                 seg1_change(mid+1,R,t[rt].k,t[rt].b,rson,t[rt].rs);
 75                 t[rt].k=a;t[rt].b=b;
 76             }
 77         }
 78         return ;
 79     }
 80     int mid=l+r>>1;
 81     if(R<=mid) seg1_change(L,R,a,b,lson,t[rt].ls);
 82     else if(L>mid) seg1_change(L,R,a,b,rson,t[rt].rs);
 83     else seg1_change(L,mid,a,b,lson,t[rt].ls),seg1_change(mid+1,R,a,b,rson,t[rt].rs);
 84 }
 85 void seg2_change(int L,int R,ll a,ll b,int l,int r,int &rt){
 86     if(!rt) {
 87         rt=++tot;
 88         t[rt].k=0;
 89         t[rt].b=-inf;
 90     }
 91     if(L==l && R==r) {
 92         t[rt].sk+=a;
 93         t[rt].sb+=b;
 94         return ;
 95     }
 96     int mid=l+r>>1;
 97     if(R<=mid) seg2_change(L,R,a,b,lson,t[rt].ls);
 98     else if(L>mid) seg2_change(L,R,a,b,rson,t[rt].rs);
 99     else seg2_change(L,mid,a,b,lson,t[rt].ls),seg2_change(mid+1,R,a,b,rson,t[rt].rs);
100 }
101 void query(int xx,int l,int r,int rt){
102     if(!rt) return ;
103     ans1+=t[rt].sk*xx+t[rt].sb;
104     ans2=max(ans2,t[rt].k*xx+t[rt].b);
105     if(l==r) return ;
106     int mid=l+r>>1;
107     if(xx<=mid) query(xx,lson,t[rt].ls);
108     else  query(xx,rson,t[rt].rs);
109 }
110 int n,m,ty,u,v,ps,rot;
111 ll a,b;
112 void solve(){
113     met(t,0);
114     tot=0;rot=0;
115     n=scan();m=scan();
116     while(m--){
117         ty=scan();
118         if(ty==3) {
119             ps=scan();
120             ans1=0;ans2=-inf;
121             query(ps,1,n,rot);
122             if(ans2<=-inf) puts("NA");
123             else printf("%lld\n",ans1+ans2);
124         }else{
125             u=scan();v=scan();a=scan();b=scan();
126             b=b-a*u;
127             if(ty==1) seg1_change(u,v,a,b,1,n,rot);
128             else seg2_change(u,v,a,b,1,n,rot);
129         }
130     }
131 }
132 int main(){
133     int t=1;
134     while(t--) solve();
135     return 0;
136 }

原文地址:https://www.cnblogs.com/cjbiantai/p/9404365.html

时间: 2024-08-29 19:25:10

[CodeChef - STREETTA] The Street 李超线段树的相关文章

李超线段树

李超线段树可以维护两两间至多有一个交点的函数覆盖,单点求极值问题. codechef NOV17 POLY 给定n个形如yi(x)=$a0+a1^x+a2x^2+a3x^3$的函数以及q个询问.每个询问给定整数t,你需要求出使得yi(t)最小化的函数yi. Lemma: Polynomial $y=x^3+ax^2+bx+c$ has at most one root greater than $k=\sqrt{\max(|b|,|c|)}+2$. Proof: Let $u\geq v >k\

【BZOJ-1568】Blue Mary开公司 李超线段树 (标记可持久化)

1568: [JSOI2008]Blue Mary开公司 Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 557  Solved: 192[Submit][Status][Discuss] Description Input 第一行 :一个整数N ,表示方案和询问的总数. 接下来N行,每行开头一个单词“Query”或“Project”. 若单词为Query,则后接一个整数T,表示Blue Mary询问第T天的最大收益. 若单词为Project,则后

【BZOJ-4515】游戏 李超线段树 + 树链剖分 + 半平面交

4515: [Sdoi2016]游戏 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 304  Solved: 129[Submit][Status][Discuss] Description Alice 和 Bob 在玩一个游戏. 游戏在一棵有 n 个点的树上进行.最初,每个点上都只有一个数字,那个数字是 123456789123456789. 有时,Alice 会选择一条从 s 到 t 的路径,在这条路径上的每一个点上都添加一个数字.对于路径上

【BZOJ4515】游戏,树链剖分+永久化标记线段树维护线段信息(李超线段树)

Time:2016.05.10 Author:xiaoyimi 转载注明出处谢谢 传送门 思路: 李超线段树 一开始听faebdc讲,并没有听的很懂ww 后来找到良心博文啊有木有 折越 首先可以把修改转换一下,因为那个dis非常不爽.显然s~t的路径有s~lca和lca~t组成.令d[x]表示x的深度,对于s~lca上面的点,修改的值相当于a*(d[s]-d[x])+b=-a*d[x]+(b-a*d[s]),lca~t上面的点的值相当于a*(d[s]+d[x]-2*d[lca])+b=a*d[x

CF932F(李超线段树+dp)

CF932F(李超线段树+dp) 此题又是新玩法, 李超线段树合并优化\(dp\) 一个显然的\(\Theta(n^2)dp\): \(dp[x]\)表示从x出发到叶子节点的最小代价 \(dp[x] = \min(dp[y] + a[x] * b[y]) ~~(y \in subtree(x))\) 如果我们将\(b[y]\)看成斜率, \(dp[y]\)看成纵截距, \(a[x]\)看成横坐标, 那么问题转为了在平面上有一些直线, 选出与直线\(x = a[x]\)相交的最靠下的点吗, 李超线

李超线段树 - JSOI2008BlueMary开公司

李超线段树用来在平面内动态插入线段,求\(x=t\)直线与这些线段交点的最值 核心是维护每个区间的"最优势线段",即终点位置处最高的线段,询问室对所有包含\(t\)的区间的最优势线段计算答案,最后取\(max\) 模板题:JSOI2008BlueMary开公司 插入直线,求单点最大值 (看代码) #include<bits/stdc++.h> using namespace std; const int N=50004; #define lc (p<<1) #d

codechef FIBTREE 码农题 线段树 树剖 标记永久化

好烦啊,调了半天 线段树部分标记比较多,手抖打错了一个 剩下的都是取模的问题 我自己瞎jb推的公式里保留了abs,但是在模意义下是gg的,所以必须把正负区分开 调试的时候一定要注意构造各种形状的树,不要只做随机树 随机树深度只有log,很难体现一些链上的性质 我用随机树拍了一下午没出错,一掏出直链就秒秒钟出错 最后找到了那个该死的abs 还是逻辑不够严谨啊 1 #include <bits/stdc++.h> 2 #define DEBUG 0 3 #define mid (l+r>&g

[bzoj1568]李超线段树模板题(标志永久化)

题意:要求在平面直角坐标系下维护两个操作: 1.在平面上加入一条线段.记第i条被插入的线段的标号为i. 2.给定一个数k,询问与直线 x = k相交的线段中,交点最靠上的线段的编号. 解题关键:注意标志的作用 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<cmath> 6 #include<iostrea

Codechef SEP14 QRECT cdq分治+线段树

题意 支持删除矩阵.插入矩阵.查询当前矩阵与之前有多少个矩阵相交 算相交的时候容斥一下:相交矩形数 = 总矩形数-X轴投影不相交的矩形数-Y轴投影不相交的矩形数-XY轴投影下都不相交的矩形数 最后一项cdq分治解决 不是我的程序--->http://wyfcyx.is-programmer.com/posts/190325.html