zoukankan      html  css  js  c++  java
  • COGS 775. 山海经 【线段树】

                                                               775. 山海经

    【问题描述】

    “南山之首日鹊山。其首日招摇之山,临于西海之上,多桂,多金玉。有草焉,其状如韭而青华,其名日祝余,食之不饥……又东三百里,日堂庭之山,多棪木,多白猿,多水玉,多黄金。

    又东三百八十里,日猨翼之山,其中多怪兽,水多怪鱼,多白玉,多蝮虫,多怪蛇,名怪木,不可以上。……”

    《山海经》是以山为纲,以海为线记载古代的河流、植物、动物及矿产等情况,而且每一条记录路线都不会有重复的山出现。某天,你的地理老师想重游《山海经》中的路线,为了简化问题,老师已经把每座山用一个整数表示他对该山的喜恶程度,他想知道第a座山到第b座山的中间某段路(i,j)。能使他感到最满意,即(i,j)这条路上所有山的喜恶度之和是(c,d)(a≤c≤d≤b)最大值。于是老师便向你请教,你能帮助他吗?值得注意的是,在《山海经》中,第i座山只能到达第i+1座山。

    【输入】

    输入第1行是两个数,n,m,2≤n≤100000,1≤m≤100000,n表示一共有n座山,m表示老师想查询的数目。

    第2行是n个整数,代表n座山的喜恶度,绝对值均小于10000。

    以下m行每行有a,b两个数,1≤a≤j≤b≤m,表示第a座山到第b座山。

    【输出】

    一共有m行,每行有3个数i,j,s,表示从第i座山到第j座山总的喜恶度为s。显然,对于每个查询,有a≤i≤j≤b,如果有多组解,则输出i最小的,如果i也相等,则输出j最小的解。

    【输入样例】

    5 3

    5 -6 3 -1 4

    1 3

    1 5

    5 5

    【输出样例】

    1 1 5

    3 5 6

    5 5 4

    我感觉炒鸡恶心 啊 

    线段树维护十个域 

    常规 的 l r 代表此区间左右端点

    ql qr 代表此区间连续子段最大的区间的左右端点

    lr 代表从左端点 最大左子串能到达的位置

    rl 代表从右端点 最大右子串能到达的位置

    lm rm代表最大左子串和最大右子串

    sum 代表区间和 

    mx代表区间最大连续子串

    建树更新,查询也要更新

      1 #include <cstdio>
      2 #include <cctype>
      3 
      4 const int MAXN=100010;
      5 
      6 int n,m;
      7 
      8 struct SegmentTree {
      9     int l,r;
     10     int ql,qr,lr,rl;
     11     int sum,lm,rm,mx;
     12 };
     13 SegmentTree t[MAXN<<2];
     14 
     15 inline void read(int&x) {
     16     int f=1;register char c=getchar();
     17     for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar());
     18     for(;isdigit(c);x=x*10+c-48,c=getchar());
     19     x=x*f;
     20 }
     21 
     22 inline int max(int a,int b) {return a<b?b:a;}
     23 
     24 inline void up(int now) {
     25     t[now].sum=t[now<<1].sum+t[now<<1|1].sum;
     26     
     27     t[now].lm=t[now<<1].lm;
     28     t[now].lr=t[now<<1].lr;
     29     if(t[now].lm<t[now<<1].sum+t[now<<1|1].lm) {
     30         t[now].lm=t[now<<1].sum+t[now<<1|1].lm;
     31         t[now].lr=t[now<<1|1].lr;
     32     }
     33     
     34     t[now].rm=t[now<<1|1].rm;
     35     t[now].rl=t[now<<1|1].rl;
     36     if(t[now].rm<=t[now<<1|1].sum+t[now<<1].rm) {
     37         t[now].rm=t[now<<1|1].sum+t[now<<1].rm;
     38         t[now].rl=t[now<<1].rl;
     39     }
     40     
     41     t[now].mx=t[now<<1].mx;
     42     t[now].ql=t[now<<1].ql;t[now].qr=t[now<<1].qr;
     43     if(t[now].mx<t[now<<1].rm+t[now<<1|1].lm) {
     44         t[now].mx=t[now<<1].rm+t[now<<1|1].lm;
     45         t[now].ql=t[now<<1].rl;
     46         t[now].qr=t[now<<1|1].lr;
     47     }
     48     if(t[now].mx<t[now<<1|1].mx){
     49         t[now].mx=t[now<<1|1].mx;
     50         t[now].ql=t[now<<1|1].ql;
     51         t[now].qr=t[now<<1|1].qr;
     52     }
     53     return;
     54 }
     55 
     56 void build_tree(int now,int l,int r) {
     57     t[now].l=l,t[now].r=r;
     58     if(l==r) {
     59         read(t[now].sum);
     60         t[now].ql=t[now].qr=l;
     61         t[now].lr=t[now].rl=l;
     62         t[now].mx=t[now].lm=t[now].rm=t[now].sum;
     63         return;
     64     }
     65     int mid=(l+r)>>1;
     66     build_tree(now<<1,l,mid);
     67     build_tree(now<<1|1,mid+1,r);
     68     up(now);
     69 }
     70 
     71 SegmentTree query(int now,int l,int r) {
     72     if(l==t[now].l&&r==t[now].r) return t[now];
     73     int mid=(t[now].l+t[now].r)>>1;
     74     SegmentTree ls,rs,ans;
     75     if(r<=mid) return query(now<<1,l,r);
     76     else if(l>mid) return query(now<<1|1,l,r);
     77     else {
     78         ls=query(now<<1,l,mid);
     79         rs=query(now<<1|1,mid+1,r);
     80         ans.l=ls.l;ans.r=rs.r;
     81         
     82         ans.lm=ls.lm;ans.lr=ls.lr;
     83         if(ans.lm<ls.sum+rs.lm) {
     84             ans.lm=ls.sum+rs.lm;
     85             ans.lr=rs.lr;
     86         }
     87         
     88         ans.rm=rs.rm;ans.rl=rs.rl;
     89         if(ans.rm<rs.sum+ls.rm) {
     90             ans.rm=rs.sum+ls.rm;
     91             ans.rl=ls.rl;
     92         }
     93         
     94         ans.sum=ls.sum+rs.sum;
     95         ans.mx=ls.mx,ans.ql=ls.ql,ans.qr=ls.qr;
     96         if(ls.rm+rs.lm>ans.mx) {
     97             ans.mx=ls.rm+rs.lm;
     98             ans.ql=ls.rl;ans.qr=rs.lr;
     99         }
    100         if(rs.mx>ans.mx) {
    101             ans.mx=rs.mx;
    102             ans.ql=rs.ql;ans.qr=rs.qr;
    103         }
    104     }
    105     return ans;
    106 }
    107 
    108 int hh() {
    109     freopen("hill.in","r",stdin);
    110     freopen("hill.out","w",stdout);
    111     read(n);read(m);
    112     build_tree(1,1,n);
    113     for(int x,y;m--;) {
    114         read(x);read(y);
    115         SegmentTree now=query(1,x,y);
    116         printf("%d %d %d
    ",now.ql,now.qr,now.mx);
    117     }
    118     return 0;
    119 }
    120 
    121 int sb=hh();
    122 int main(int argc,char**argv) {;}
    代码


    作者:乌鸦坐飞机
    出处:http://www.cnblogs.com/whistle13326/
    新的风暴已经出现 怎么能够停止不前 穿越时空 竭尽全力 我会来到你身边 微笑面对危险 梦想成真不会遥远 鼓起勇气 坚定向前 奇迹一定会出现

     
  • 相关阅读:
    日常学习——FFT
    poj 3353 Road Construction tarjan 边双联通分支 缩点+结论
    4612 warm up tarjan+bfs求树的直径(重边的强连通通分量)忘了写了,今天总结想起来了。
    tarjan总结
    hdu 4655 Cut Pieces 找规律
    POJ3592 Instantaneous Transference tarjan +spfa
    hdu 4647 Another Graph Game
    hdu4638 group 树状数组
    4630 no pain no game 树状数组
    hdu 4619 Warm up 2 网络流 最小割
  • 原文地址:https://www.cnblogs.com/whistle13326/p/7466897.html
Copyright © 2011-2022 走看看