[CodeChef - STREETTA] The Street 李超线段树
Posted cjbiantai
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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 ",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 }
以上是关于[CodeChef - STREETTA] The Street 李超线段树的主要内容,如果未能解决你的问题,请参考以下文章