cogs 775 山海经

775. 山海经

★★★   输入文件:hill.in   输出文件:hill.out   简单对比
时间限制:1 s   内存限制:128 MB

【问题描述】

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

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

《山海经》是以山为纲,以海为线记载古代的河流、植物、动物及矿产等情况,而且每一条记录路线都不会有重复的山出现。某天,你的地理老师想重游《山海经》中的路线,为了简化问题,老师已经把每座山用一个整数表示他对该山的喜恶程度,他想知道第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

solution:

    这个题就是一个裸地线段树,只不过在维护的时候有一些麻烦。需要维护有以下几个域,最大左子串(一定由区间最左端开始),右子串(一定由区间右子串开始),中间的字串(左右端点一点不在区间的左右端点),整个区间的sum,以及对应前三个域的左右边界,pushup的时候把以上几个变量更新在更新以下对应的左右边界即可,但要注意的是顺序,此题要求i、j都最小,在最后输出时先判断左子串,然后sum,然后mid,然后右子串。

    

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 #define inf 0x7fffffff
  7 int n,m;
  8 struct node {
  9     int sum,l,r,mid;
 10     int l1,r1,l2,r2,l3,r3;
 11     int ll,rr;
 12     node() {
 13         sum=l=r=mid=-inf;
 14     }
 15 } tree[4*100001],null;
 16 int a[100005];
 17 void pushup(int x) {
 18     tree[x].sum=tree[x<<1].sum+tree[x<<1|1].sum;
 19     if(tree[x<<1].l>=tree[x].l) {
 20         tree[x].l=tree[x<<1].l;
 21         tree[x].l1=tree[x<<1].l1;
 22         tree[x].r1=tree[x<<1].r1;
 23     }
 24     if(tree[x<<1].sum>tree[x].l) {
 25         tree[x].l=tree[x<<1].sum;
 26         tree[x].l1=tree[x<<1].ll;
 27         tree[x].r1=tree[x<<1].rr;
 28     }
 29     if(tree[x<<1].sum+tree[x<<1|1].l>tree[x].l) {
 30         tree[x].l=tree[x<<1].sum+tree[x<<1|1].l;
 31         tree[x].l1=tree[x<<1].ll;
 32         tree[x].r1=tree[(x<<1|1)].r1;
 33     }
 34     if(tree[x<<1|1].sum+tree[x<<1].r>=tree[x].r) {
 35         tree[x].r=tree[x<<1|1].sum+tree[x<<1].r;
 36         tree[x].l2=tree[x<<1].l2;
 37         tree[x].r2=tree[x<<1|1].rr;
 38     }
 39     if(tree[x<<1|1].sum>tree[x].r) {
 40         tree[x].r=tree[x<<1|1].sum;
 41         tree[x].l2=tree[x<<1|1].ll;
 42         tree[x].r2=tree[x<<1|1].rr;
 43     }
 44     if(tree[x<<1|1].r>tree[x].r) {
 45         tree[x].r=tree[x<<1|1].r;
 46         tree[x].l2=tree[(x<<1|1)].l2;
 47         tree[x].r2=tree[x<<1|1].r2;
 48     }
 49     if(tree[x<<1].mid>=tree[x].mid) {
 50         tree[x].mid=tree[x<<1].mid;
 51         tree[x].l3=tree[x<<1].l3;
 52         tree[x].r3=tree[x<<1].r3;
 53     }
 54     if(tree[x<<1].r>tree[x].mid) {
 55         tree[x].mid=tree[x<<1].r;
 56         tree[x].l3=tree[x<<1].l2;
 57         tree[x].r3=tree[x<<1].r2;
 58     }
 59     if(tree[x<<1|1].l+tree[x<<1].r>tree[x].mid) {
 60         tree[x].mid=tree[x<<1|1].l+tree[x<<1].r;
 61         tree[x].l3=tree[x<<1].l2;
 62         tree[x].r3=tree[x<<1|1].r1;
 63     }
 64     if(tree[x<<1|1].l>tree[x].mid) {
 65         tree[x].mid=tree[x<<1|1].l;
 66         tree[x].l3=tree[x<<1|1].l1;
 67         tree[x].r3=tree[x<<1|1].r1;
 68     }
 69     if(tree[x<<1|1].mid>tree[x].mid) {
 70         tree[x].mid=tree[x<<1|1].mid;
 71         tree[x].l3=tree[x<<1|1].l3;
 72         tree[x].r3=tree[x<<1|1].r3;
 73     }
 74 }
 75 void build(int i,int le,int ri) {
 76     if(le==ri) {
 77         tree[i].sum=tree[i].l=tree[i].r=tree[i].mid=a[le];
 78         tree[i].ll=tree[i].rr=le;
 79         tree[i].l1=tree[i].r1=tree[i].l2=tree[i].r2=tree[i].l3=tree[i].r3=le;
 80         return ;
 81     }
 82     tree[i].ll=le;
 83     tree[i].rr=ri;
 84     int mid=le+ri>>1;
 85     build(i<<1,le,mid);
 86     build(i<<1|1,mid+1,ri);
 87     pushup(i);
 88 }
 89 node query(int i,int L,int R,int l,int r) {
 90     if(l>r) {
 91         return null;
 92     }
 93     if(l<=L&&R<=r) {
 94         return tree[i];
 95     }
 96     int mid=L+R>>1;
 97     node ans1,ans2;
 98     if(l<=mid) {
 99         ans1=query(i<<1,L,mid,l,r);
100     }
101     if(r>mid) {
102         ans2=query(i<<1|1,mid+1,R,l,r);
103     }
104     node ans;
105     if(ans1.sum<=-2147483645&&ans2.sum<=-2147483645) {
106         return ans1;
107     }
108     if(ans1.sum<=-2147483645) {
109         return ans2;
110     }
111     if(ans2.sum<=-2147483645) {
112         return ans1;
113     }
114     ans.sum=ans1.sum+ans2.sum;
115     if(ans1.l>=ans.l) {
116         ans.l=ans1.l;
117         ans.l1=ans1.l1;
118         ans.r1=ans1.r1;
119     }
120     if(ans1.sum>ans.l) {
121         ans.l=ans1.sum;
122         ans.l1=ans1.ll;
123         ans.r1=ans1.rr;
124     }
125     if(ans1.sum+ans2.l>ans.l) {
126         ans.l=ans1.sum+ans2.l;
127         ans.l1=ans1.ll;
128         ans.r1=ans2.r1;
129     }
130     if(ans2.sum+ans1.r>=ans.r) {
131         ans.r=ans2.sum+ans1.r;
132         ans.l2=ans1.l2;
133         ans.r2=ans2.rr;
134     }
135     if(ans2.sum>ans.r) {
136         ans.r=ans2.sum;
137         ans.l2=ans2.ll;
138         ans.r2=ans2.rr;
139     }
140     if(ans2.r>ans.r) {
141         ans.r=ans2.r;
142         ans.l2=ans2.l2;
143         ans.r2=ans2.r2;
144     }
145     if(ans1.mid>=ans.mid) {
146         ans.mid=ans1.mid;
147         ans.l3=ans1.l3;
148         ans.r3=ans1.r3;
149     }
150     if(ans1.r>ans.mid) {
151         ans.mid=ans1.r;
152         ans.l3=ans1.l2;
153         ans.r3=ans1.r2;
154     }
155     if(ans2.l+ans1.r>ans.mid) {
156         ans.mid=ans2.l+ans1.r;
157         ans.l3=ans1.l2;
158         ans.r3=ans2.r1;
159     }
160     if(ans2.l>ans.mid) {
161         ans.mid=ans2.l;
162         ans.l3=ans2.l1;
163         ans.r3=ans2.r1;
164     }
165     if(ans2.mid>ans.mid) {
166         ans.mid=ans2.mid;
167         ans.l3=ans2.l3;
168         ans.r3=ans2.r3;
169     }
170     ans.ll=min(ans1.ll,ans2.ll);
171     ans.rr=max(ans1.rr,ans2.rr);
172     return ans;
173 }
174 int main() {
175     freopen("hill.in","r",stdin);
176     freopen("hill.out","w",stdout);
177     scanf("%d%d",&n,&m);
178     for(int i=1; i<=n; i++) {
179         scanf("%d",&a[i]);
180     }
181     build(1,1,n);
182     for(int i=1,a,b; i<=m; i++) {
183         scanf("%d%d",&a,&b);
184         node ans=query(1,1,n,a,b);
185         if(ans.l>=ans.sum&&ans.l>=ans.r&&ans.l>=ans.mid) {
186             printf("%d %d %d\n",ans.l1,ans.r1,ans.l);
187             continue;
188         }
189         if(ans.sum>=ans.l&&ans.sum>=ans.r&&ans.sum>=ans.mid) {
190             printf("%d %d %d\n",ans.ll,ans.rr,ans.sum);
191             continue;
192         }
193         if(ans.mid>=ans.sum&&ans.mid>=ans.l&&ans.mid>=ans.r) {
194             printf("%d %d %d\n",ans.l3,ans.r3,ans.mid);
195             continue;
196         }
197         if(ans.r>=ans.sum&&ans.r>=ans.l&&ans.r>=ans.mid) {
198             printf("%d %d %d\n",ans.l2,ans.r2,ans.r);
199             continue;
200         }
201     }
202     return 0;
203 }
时间: 2024-10-21 22:42:41

cogs 775 山海经的相关文章

COGS 775. 山海经 【线段树】

775. 山海经 [问题描述] “南山之首日鹊山.其首日招摇之山,临于西海之上,多桂,多金玉.有草焉,其状如韭而青华,其名日祝余,食之不饥……又东三百里,日堂庭之山,多棪木,多白猿,多水玉,多黄金. 又东三百八十里,日猨翼之山,其中多怪兽,水多怪鱼,多白玉,多蝮虫,多怪蛇,名怪木,不可以上.……” <山海经>是以山为纲,以海为线记载古代的河流.植物.动物及矿产等情况,而且每一条记录路线都不会有重复的山出现.某天,你的地理老师想重游<山海经>中的路线,为了简化问题,老师已经把每座山用

【cogs 775】山海经 ——Segment Tree

题目链接:      TP 题解:   我数据结构真心是弱啊= =. 线段树好厉害啊,一直不会区间最大连续和,今天刚学习了一下233. 维护前缀最大和后缀最大,越界最大(?),再维护一个区间最大,瞎搞搞就好了,RE了一遍233. 代码:  1 #define Troy 2 3 #include <bits/stdc++.h> 4 5 using namespace std; 6 7 inline int read(){ 8 int s=0,k=1;char ch=getchar(); 9 wh

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

前几天看mike的ppt发现有线段树的题,就挑了第一道题搞搞吧,然后就gg了,花了三天时间总算搞掉了 先放题: 775. 山海经 ★★★☆   输入文件:hill.in   输出文件:hill.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] “南山之首日鹊山.其首日招摇之山,临于西海之上,多桂,多金玉.有草焉,其状如韭而青华,其名日祝余,食之不饥……又东三百里,日堂庭之山,多棪木,多白猿,多水玉,多黄金. 又东三百八十里,日猨翼之山,其中多怪兽,水多怪鱼,多白玉,

cogs775 山海经 线段树

链接:http://cogs.pro/cogs/problem/problem.php?pid=775 题意:维护区间最大值及其最小字典序来源. 细节巨多--多的狗死人了-- 首先我们要建出一棵线段树,这棵线段树要存放以下几个东西:最长区间,起点,终点,最长前缀,前缀终点,最长后缀,后缀起点.(所以维护打了足足六十行--查询打了三十行--) 如何查询呢?最长序列无外乎三种情况: 1.全在左子树中.我们设$len[i]$为$i$节点最长序列,则此时$len[i]=len[i<<1]$: 2.全在

【线段树】【SOJ1136】【cogs775】山海经

775. [SOJ 1136] 山海经 ★★★   输入文件:hill.in   输出文件:hill.out   简单对比 时间限制:1 s   内存限制:128 MB [问题描述] "南山之首日鹊山.其首日招摇之山,临于西海之上,多桂,多金玉.有草焉,其状如韭而青华,其名日祝余,食之不饥--又东三百里,日堂庭之山,多棪木,多白猿,多水玉,多黄金. 又东三百八十里,日猨翼之山,其中多怪兽,水多怪鱼,多白玉,多蝮虫,多怪蛇,名怪木,不可以上.--" <山海经>是以山为纲,以海

COGS基本法初稿

COGS基本法 序言 我们COGS人民,为建立更完善的联盟,树立正义,保障网络安宁,提供公共OJ,杜绝极少数恐怖分子对我OJ的破坏行为,并使我们自己和OIER得享自由的幸福,特为COGS制定本基本法. 第一条权利机构 权利机构由老常为领导核心的第一代领导集体及COGS QQ群的元老组成,COGS的权力机构为君主立宪制,其中老常为世袭君主,议会由首相刘易铖,长老王梦迪,内阁大臣张灵犀,外交大臣张子昂.国家工程师李冬麟组成.首相.内阁大臣.外交大臣必须由河南省实验中学有着良好素质和学习水平的学生组成

COGS——T 2739. 凯伦和咖啡

http://www.cogs.pro/cogs/problem/problem.php?pid=2739 ★★☆   输入文件:coffee.in   输出文件:coffee.out   简单对比时间限制:1 s   内存限制:512 MB [题目描述] 为了在上课时保持清醒,凯伦需要一些咖啡.咖啡爱好者凯伦想知道最佳的温度来冲煮完美的咖啡.因此,她花了一些时间阅读几本食谱,其中包括广受好评的“咖啡的艺术”. 她知道有n个食谱,其中第i个食谱建议应当在li和ri度之间冲煮以达到最佳的味道.凯伦

COGS——T 8. 备用交换机

http://www.cogs.pro/cogs/problem/problem.php?pid=8 ★★   输入文件:gd.in   输出文件:gd.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] n个城市之间有通讯网络,每个城市都有通讯交换机,直接或间接与其它城市连接.因电子设备容易损坏,需给通讯点配备备用交换机.但备用交换机数量有限,不能全部配备,只能给部分重要城市配置.于是规定:如果某个城市由于交换机损坏,不仅本城市通讯中断,还造成其它城市通讯中断,则配

COGS——C2098. Asm.Def的病毒

http://www.cogs.pro/cogs/problem/problem.php?pid=2098 ★☆   输入文件:asm_virus.in   输出文件:asm_virus.out   简单对比时间限制:1 s   内存限制:256 MB [题目描述] “这就是我们最新研制的,世界上第一种可持久化动态计算机病毒,‘创世纪’.”方教授介绍道. “哦.”主席面无表情地点点头. “‘创世纪’无法真正杀死透明计算网络,但是可以把它变成傻子.可惜透明计算网络能轻松地辨认出病毒,所以我建议……