cogs775 山海经 线段树

Posted Loser Of Life

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了cogs775 山海经 线段树相关的知识,希望对你有一定的参考价值。

链接:http://cogs.pro/cogs/problem/problem.php?pid=775

题意:维护区间最大值及其最小字典序来源。

细节巨多……多的狗死人了……

首先我们要建出一棵线段树,这棵线段树要存放以下几个东西:最长区间,起点,终点,最长前缀,前缀终点,最长后缀,后缀起点。(所以维护打了足足六十行……查询打了三十行……)

如何查询呢?最长序列无外乎三种情况:

1、全在左子树中。我们设$len[i]$为$i$节点最长序列,则此时$len[i]=len[i<<1]$;

2、全在右子树中,同理可以得出$len[i]=len[i<<1|1]$。

3、横跨两个子树。设前缀长为$pre[i]$,后缀长为$suf[i]$,那么$len[i]=suf[i<<1]+pre[i<<1|1]$。

维护时顺带按照长度第一字典序第二要求维护区间起终点即可。

查询时按照相同方法进行查询,需要注意的是,最后一次合并时左右可能并未完全更新,上传完成后还要再找一次最优解。

技术分享
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 using namespace std;
  6 const int maxn=100005,inf=0x3f3f3f3f;
  7 struct node
  8 {
  9     int l,r,lmax,rmax,st,en,totmax,pre,suf,sum;
 10     node()
 11     {
 12         lmax=rmax=totmax=-inf;sum=0;
 13     }
 14 }segtree[maxn<<2];
 15 #define mid ((l+r)>>1)
 16 #define lc root<<1
 17 #define rc root<<1|1
 18 #define lson lc,l,mid
 19 #define rson rc,mid+1,r
 20 void pushup(int root)
 21 {
 22     segtree[root].sum=segtree[lc].sum+segtree[rc].sum;
 23     if(segtree[lc].lmax<segtree[lc].sum+segtree[rc].lmax)
 24     {
 25         segtree[root].lmax=segtree[lc].sum+segtree[rc].lmax;
 26         segtree[root].pre=segtree[rc].pre;
 27     }
 28     else 
 29     {
 30         segtree[root].lmax=segtree[lc].lmax;
 31         segtree[root].pre=segtree[lc].pre;
 32     }
 33     if(segtree[rc].rmax<segtree[rc].sum+segtree[lc].rmax)
 34     {
 35         segtree[root].rmax=segtree[rc].sum+segtree[lc].rmax;
 36         segtree[root].suf=segtree[lc].suf;
 37     }
 38     else 
 39     {
 40         segtree[root].rmax=segtree[rc].rmax;
 41         segtree[root].suf=segtree[rc].suf;
 42     }
 43     if(segtree[lc].totmax<segtree[rc].totmax)
 44     {
 45         if(segtree[rc].totmax<=segtree[lc].rmax+segtree[rc].lmax)
 46         {
 47                 segtree[root].totmax=segtree[lc].rmax+segtree[rc].lmax;
 48                 segtree[root].st=segtree[lc].suf;
 49                 segtree[root].en=segtree[rc].pre;
 50         }
 51         else 
 52         {
 53             segtree[root].totmax=segtree[rc].totmax;
 54             segtree[root].st=segtree[rc].st;
 55             segtree[root].en=segtree[rc].en;
 56         }
 57     }
 58     else if(segtree[lc].totmax<segtree[lc].rmax+segtree[rc].lmax)
 59     {
 60         segtree[root].totmax=segtree[lc].rmax+segtree[rc].lmax;
 61         segtree[root].st=segtree[lc].suf;
 62         segtree[root].en=segtree[rc].pre;
 63     }
 64     else if(segtree[lc].totmax==segtree[lc].rmax+segtree[rc].lmax)
 65     {
 66         segtree[root].totmax=segtree[lc].totmax;
 67         if(segtree[lc].st>segtree[lc].suf)
 68         {
 69             segtree[root].st=segtree[lc].suf;
 70             segtree[root].en=segtree[rc].pre;
 71         }
 72         else 
 73         {
 74             segtree[root].st=segtree[lc].st;
 75             segtree[root].en=segtree[root].en;
 76         }
 77     }
 78     else 
 79     {
 80         segtree[root].totmax=segtree[lc].totmax;
 81         segtree[root].st=segtree[lc].st;
 82         segtree[root].en=segtree[lc].en;
 83     }
 84 }
 85 void cmp(node x,node y,node &z)
 86 {
 87     z.l=x.l,z.r=y.r;z.sum=x.sum+y.sum;
 88     if(x.lmax<x.sum+y.lmax)
 89     {
 90         z.lmax=x.sum+y.lmax;
 91         z.pre=y.pre;
 92     }
 93     else z.lmax=x.lmax,z.pre=x.pre;
 94     if(y.rmax<y.sum+x.rmax)
 95     {
 96         z.rmax=y.sum+x.rmax;
 97         z.suf=x.suf;
 98     }
 99     else 
100     {
101         z.rmax=y.rmax;
102         z.suf=y.suf;
103     }
104     if(x.totmax<y.totmax)
105     {
106         if(y.totmax<=x.rmax+y.lmax)
107         {
108             z.totmax=x.rmax+y.lmax;
109             z.st=x.suf;
110             z.en=y.pre;
111         }
112         else 
113         {
114             z.totmax=y.totmax;
115             z.st=y.st;
116             z.en=y.en;
117         }
118     }
119     else if(x.totmax<x.rmax+y.lmax)
120     {
121         z.totmax=x.rmax+y.lmax;
122         z.st=x.suf;
123         z.en=y.pre;
124     }
125     else if(x.totmax==x.rmax+y.lmax)
126     {
127         z.totmax=x.totmax;
128         if(x.suf<x.st)z.st=x.suf,z.en=y.pre;
129         else z.st=x.st,z.en=x.en;
130     }
131     else z.totmax=x.totmax,z.st=x.st,z.en=x.en;
132 }
133 void build(int root,int l,int r)
134 {
135     segtree[root].l=l,segtree[root].r=r;
136     if(l==r)
137     {
138         int tmp;scanf("%d",&tmp);
139         segtree[root].sum=segtree[root].lmax=segtree[root].rmax=segtree[root].totmax=tmp;
140         segtree[root].st=segtree[root].en=segtree[root].pre=segtree[root].suf=l;
141         return;
142     }
143     build(lson),build(rson);
144     pushup(root);
145 }
146 #undef mid
147 void print(node t)
148 {
149     if(t.lmax>=t.rmax)
150         if(t.lmax>=t.totmax)printf("%d %d %d\n",t.l,t.pre,t.lmax);
151         else printf("%d %d %d\n",t.st,t.en,t.totmax);
152     else if(t.rmax>t.totmax)printf("%d %d %d\n",t.suf,t.r,t.rmax);
153     else printf("%d %d %d\n",t.st,t.en,t.totmax);
154 }
155 node query(int root,int l,int r)
156 {
157     if(segtree[root].l>=l&&segtree[root].r<=r)
158         return segtree[root];
159     int mid=segtree[root].l+segtree[root].r>>1;node t1,t2,t3;
160     if(l<=mid)t1=query(lc,l,r);if(r>mid)t2=query(rc,l,r);
161     t1.l=l,t1.r=mid,t2.l=mid+1,t2.r=r;
162     cmp(t1,t2,t3);return t3;
163 }
164 int n,q;
165 int haha()
166 {
167     freopen("hill.in","r",stdin);
168     freopen("hill.out","w",stdout);
169     scanf("%d%d",&n,&q);
170     build(1,1,n);
171     for(int i=1;i<=q;i++)
172     {
173         int x,y;scanf("%d%d",&x,&y);
174         node t=query(1,x,y);
175         print(t);
176     }
177 }
178 int sb=haha();
179 int main(){;}
cogs775

 


.


以上是关于cogs775 山海经 线段树的主要内容,如果未能解决你的问题,请参考以下文章

cogs 775山海经 ——Segment Tree

cogs 775 山海经

山海经 (线段树高阶操作)

COGS 2638. 数列操作ψ 线段树

COGS 265线段覆盖[线段树]

COGS 2554. [福利]可持久化线段树