[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 }
View Code

 

以上是关于[CodeChef - STREETTA] The Street 李超线段树的主要内容,如果未能解决你的问题,请参考以下文章

Codechef 虫洞:我的逻辑有啥问题?

Codechef RIN 「Codechef14DEC」Course Selection 最小割离散变量模型

codechef Suffix Palindromes

IDE 中的代码正确,但 CodeChef 中出现错误

Codechef Course Selection

CodeChef CBAL