zoukankan      html  css  js  c++  java
  • uvalive 3938 "Ray, Pass me the dishes!" 线段树 区间合并

    题意:求q次询问的静态区间连续最大和起始位置和终止位置 输出字典序最小的解.

    思路:刘汝佳白书 每个节点维护三个值

    pre, sub, suf 最大的前缀和, 连续和, 后缀和 然后这个题还要记录解的位置所以还要区间总和sum

      1 #include<iostream>
      2 #include<string>
      3 #include<algorithm>
      4 #include<cstdlib>
      5 #include<cstdio>
      6 #include<set>
      7 #include<map>
      8 #include<vector>
      9 #include<cstring>
     10 #include<stack>
     11 #include<cmath>
     12 #include<queue>
     13 #include <bits/stdc++.h>
     14 using namespace std;
     15 #define INF 0x3f3f3f3f
     16 #define ll long long
     17 #define clc(a,b) memset(a,b,sizeof(a))
     18 
     19 const int maxn = 500000 + 10;
     20 const int maxnode = 1000000 + 10;
     21 typedef long long LL;
     22 typedef pair<int,int> Interval;
     23 
     24 LL prefix_sum[maxn];
     25 
     26 LL sum(int L, int R)
     27 {
     28     return prefix_sum[R] - prefix_sum[L-1];
     29 }
     30 
     31 LL sum(Interval p)
     32 {
     33     return sum(p.first, p.second);
     34 }
     35 
     36 Interval better(Interval a, Interval b)
     37 {
     38     if(sum(a) != sum(b)) return sum(a) > sum(b) ? a : b;
     39     return a < b ? a : b; // 利用pair自带的字典序
     40 }
     41 
     42 int qL, qR;
     43 
     44 struct IntervalTree
     45 {
     46     int max_prefix[maxnode];
     47     int max_suffix[maxnode];
     48     Interval max_sub[maxnode];
     49 
     50     void build(int o, int L, int R)
     51     {
     52         if(L == R)
     53         {
     54             max_prefix[o] = max_suffix[o] = L;
     55             max_sub[o] = make_pair(L, L);
     56         }
     57         else
     58         {
     59             int M = L + (R-L)/2;
     60             // 递归创建子树
     61             int lc = o*2, rc = o*2+1;
     62             build(lc, L, M);
     63             build(rc, M+1, R);
     64 
     65             // 递推max_prefix
     66             LL v1 = sum(L, max_prefix[lc]);
     67             LL v2 = sum(L, max_prefix[rc]);
     68             if(v1 == v2) max_prefix[o] = min(max_prefix[lc], max_prefix[rc]);
     69             else max_prefix[o] = v1 > v2 ? max_prefix[lc] : max_prefix[rc];
     70 
     71             // 递推max_suffix
     72             v1 = sum(max_suffix[lc], R);
     73             v2 = sum(max_suffix[rc], R);
     74             if(v1 == v2) max_suffix[o] = min(max_suffix[lc], max_suffix[rc]);
     75             else max_suffix[o] = v1 > v2 ? max_suffix[lc] : max_suffix[rc];
     76 
     77             // 递推max_sub
     78             max_sub[o] = better(max_sub[lc], max_sub[rc]); // 完全在左子树或者右子树
     79             max_sub[o] = better(max_sub[o], make_pair(max_suffix[lc], max_prefix[rc])); // 跨越中线
     80         }
     81     }
     82 
     83     Interval query_prefix(int o, int L, int R)
     84     {
     85         if(max_prefix[o] <= qR) return make_pair(L, max_prefix[o]);
     86         int M = L + (R-L)/2;
     87         int lc = o*2, rc = o*2+1;
     88         if(qR <= M) return query_prefix(lc, L, M);
     89         Interval i = query_prefix(rc, M+1, R);
     90         i.first = L;
     91         return better(i, make_pair(L, max_prefix[lc]));
     92     }
     93 
     94     Interval query_suffix(int o, int L, int R)
     95     {
     96         if(max_suffix[o] >= qL) return make_pair(max_suffix[o], R);
     97         int M = L + (R-L)/2;
     98         int lc = o*2, rc = o*2+1;
     99         if(qL > M) return query_suffix(rc, M+1, R);
    100         Interval i = query_suffix(lc, L, M);
    101         i.second = R;
    102         return better(i, make_pair(max_suffix[rc], R));
    103     }
    104 
    105     Interval query(int o, int L, int R)
    106     {
    107         if(qL <= L && R <= qR) return max_sub[o];
    108         int M = L + (R-L)/2;
    109         int lc = o*2, rc = o*2+1;
    110         if(qR <= M) return query(lc, L, M);
    111         if(qL > M) return query(rc, M+1, R);
    112         Interval i1 = query_prefix(rc, M+1, R); // 右半的前缀
    113         Interval i2 = query_suffix(lc, L, M); // 左半的后缀
    114         Interval i3 = better(query(lc, L, M), query(rc, M+1, R));
    115         return better(make_pair(i2.first, i1.second), i3);
    116     }
    117 };
    118 
    119 IntervalTree tree;
    120 
    121 int main()
    122 {
    123     int kase = 0, n, a, Q;
    124     while(scanf("%d%d", &n, &Q) == 2)
    125     {
    126         prefix_sum[0] = 0;
    127         for(int i = 0; i < n; i++)
    128         {
    129             scanf("%d", &a);
    130             prefix_sum[i+1] = prefix_sum[i] + a;
    131         }
    132         tree.build(1, 1, n);
    133         printf("Case %d:
    ", ++kase);
    134         while(Q--)
    135         {
    136             int L, R;
    137             scanf("%d%d", &L, &R);
    138             qL = L;
    139             qR = R;
    140             Interval ans = tree.query(1, 1, n);
    141             printf("%d %d
    ", ans.first, ans.second);
    142         }
    143     }
    144     return 0;
    145 }
    View Code
  • 相关阅读:
    CMDXP.CMD命令大全
    ASP.NET 页生命周期概述
    使用 ASP.NET 2.0提供的WebResource管理资源
    软件包管理 之 Fedora / Redhat 软件包管理指南
    开源代码分析研究 之 BugNet (2008年1月14日更新 第一章BugNet 简介 已完成)
    软件包管理 之 如何编译安装源码包软件
    硬件管理 之 Linux 硬件管理的基础知识
    软件包管理 之 fedorarpmdevtools 工具介绍
    软件包管理 之 Fedora/Redhat 在线安装更新软件包,yum 篇 ── 给新手指南
    系统引导管理 之 系统引导过程及硬盘分区结构论述
  • 原文地址:https://www.cnblogs.com/ITUPC/p/5193735.html
Copyright © 2011-2022 走看看