2019杭电多校第六场hdu6638 Snowy Smile(线段树+枚举)

Snowy Smile

题目传送门

解题思路

先把y离散化,然后把点按照x的大小进行排序,我们枚举每一种x作为上边界,然后再枚举其对应的每一种下边界。按照这种顺序插入点,这是一个压维的操作,即在线段树中的y位置加上其w,并利用线段树来更新动态的最大子段和。

代码如下

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;

const int N = 2005;

struct T{
    ll x, y, w;
    T(){}
    T(ll x, ll y, ll w): x(x), y(y), w(w){}
}a[N];

bool cmp(const T& a, const T& b)
{
    return a.x < b.x;
}

int b[N];

struct {
    int l, r;
    ll lx, rx, mx;
    ll sum;
}tree[N << 2];

void build(int k, int l, int r)
{
    tree[k].l = l;
    tree[k].r = r;
    tree[k].sum = tree[k].lx = tree[k].rx = tree[k].mx = 0;
    if(l == r)
        return;
    int mid = (l + r) / 2;
    build(2*k, l, mid);
    build(2*k + 1, mid + 1, r);
}

void push_up(int k)
{
    tree[k].sum = tree[2*k].sum + tree[2*k+1].sum;
    tree[k].lx = max(tree[2*k].lx, tree[2*k].sum + tree[2*k+1].lx);
    tree[k].rx = max(tree[2*k+1].rx, tree[2*k+1].sum + tree[2*k].rx);
    tree[k].mx = max(max(tree[2*k].mx, tree[2*k+1].mx), tree[2*k].rx + tree[2*k+1].lx);
}

void insert(int k, int x, int w)
{
    if(tree[k].l == tree[k].r){
        tree[k].sum = tree[k].lx = tree[k].rx = tree[k].mx = tree[k].mx + w;
        return;
    }
    int mid = (tree[k].l + tree[k].r) / 2;
    if(x <= mid)
        insert(2*k, x, w);
    else
        insert(2*k+1, x, w);
    push_up(k);
}

inline ll query()
{
    return tree[1].mx;
}

int main()
{
    ios::sync_with_stdio(false);
    int t;
    cin >> t;
    while(t --){
        int n;
        cin >> n;
        for(int i = 1; i <= n; i ++){
            ll x, y, w;
            cin >> x >> y >> w;
            a[i] = T(x, y, w);
            b[i] = y;
        }
        sort(b + 1, b + n + 1);
        int k = unique(b + 1, b + n + 1) - b - 1;
        for(int i = 1; i <= n; i ++){
            int y = lower_bound(b + 1, b + k + 1, a[i].y) - b;
            a[i].y = y;
        }
        sort(a + 1, a + n + 1, cmp);
        ll ans = 0;
        for(int i = 1; i <= n; i ++){
            if(i != 1 && a[i].x == a[i - 1].x)
                continue;
            build(1, 1, k);
            for(int j = i; j <= n; j ++){
                if(j != i && a[j].x != a[j - 1].x)
                    ans = max(ans, query());
                insert(1, a[j].y, a[j].w);
            }
            ans = max(ans, query());
        }
        cout << ans << endl;
    }
    return 0;
}

原文地址:https://www.cnblogs.com/whisperlzw/p/11318112.html

时间: 2024-11-08 01:33:21

2019杭电多校第六场hdu6638 Snowy Smile(线段树+枚举)的相关文章

2019 杭电多校 第六场

2019 Multi-University Training Contest 6 补题链接:2019 Multi-University Training Contest 6 1002 Nonsense Time (HDU 6635) 题意 给定包含 \(n\) 个不同数字的排列 \(p\).一开始所有数字都冻住.再给出一个长度为 \(n\) 的数组 \(k\),\(k[i]\) 表示 \(p[k[i]]\) 在第 \(i\) 时刻解冻.输出 \(n\) 个数,表示第 \(i\) 个时刻数组 \(

[2019杭电多校第六场][hdu6635]Nonsense Time

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6635 题意是说一开始所有数都冻结,第i秒会解冻第ki个数,求每秒状态下的最长上上升子序列长度. 这种题一想添加操作就不好实现,所以干脆反着来,想删除操作. 从第n秒开始往前遍历,每次都会冻结一个数,这时判断一下这个数是否一定要在最长上升子序列里. 使用二分的方法求最长上升子序列,并且每次求完子序列后可以处理出那些位置是必须在最长上升子序列里的. 1 #include<iostream> 2 #in

2019 杭电多校 第五场

2019 Multi-University Training Contest 5 补题链接:2019 Multi-University Training Contest 5 罚时爆炸 自闭场 1004 equation (HDU 6627) 题意: 给定一个整数 \(C\) 和 \(N\) 组 \(a_i,b_i\),求 \(∑_{i=1}^N|a_i\cdot x + b_i| = C\) 的所有解,如果有无穷多个解就输出 -1. 思路 分类讨论 分类讨论去绝对值.根据 \(b_i / a_i

2019 杭电多校 第八场

2019 Multi-University Training Contest 8 补题链接:2019 Multi-University Training Contest 8 1003 Acesrc and Good Numbers HDU 6659 题意 定义 \(f(d, n)\) 为十进制下 \(1\) 到 \(n\) 所有数的数位中数字 \(d\) 出现的次数.给定 \(x\),找出最大的 \(n(n \le x)\) 满足 \(f(d, n) = n\). 题解 看到了一个神仙做法. 显

2019 杭电多校 第七场

2019 Multi-University Training Contest 7 补题链接:2019 Multi-University Training Contest 7 1001 A + B = C 题意: 给出 \(a, b, c\),求 \(x, y, z\) 满足 \(a\cdot 10^x + b\cdot 10^y = c\cdot 10^z\).\(a, b, c \le 10^{100000}\). 题解: 补零到 \(a, b, c\) 长度相等之后,可能的情况只有四种: \

2019 杭电多校 第四场

2019 Multi-University Training Contest 4 补题链接:2019 Multi-University Training Contest 4 1001 AND Minimum Spanning Tree (HDU 6614) 题意 给定一个有 \(N\) 个结点的完全图,编号从 \(1\) 到 \(N\).结点 \(x\) 与结点 \(y\) \((1\leq x, y\leq N, x \neq y)\) 的边的权值为 \(x\) 与 \(y\) 按位与的值,求

2019 杭电多校 第三场

2019 Multi-University Training Contest 3 补题链接:2019 Multi-University Training Contest 3 1002 Blow up the city (HDU-6604) 题意 给定 \(n\) 个点和 \(m\) 条边的有向无环图,给出 \(q\) 次询问,每个询问给出 \(a\) 和 \(b\),求有多少个点,满足该点删去后 \(a\) 和 \(b\) 中至少一个点不能到达出度为 \(0\) 的点. 题解 支配树/灭绝树 拓

2019杭电多校第三场 1004 Distribution of books

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6606 考虑二分答案,我们二分一个值\(x\),那么要怎么来验证这个答案是否可行,考虑dp求解,设\(dp[i]\)为前i个在答案为\(x\)的情况下划分最最多组数,那么若\(dp[n] \geq k\) 则这个x可行, 很显然可以看出\(x\)是单调的,所以二分. \[dp[i] = max(dp[j]) + 1 (sum[i] - sum[j-1] \leq x)\] 如果直接采用暴力枚举的话复杂

2019年杭电多校第三场 1011题Squrirrel(HDU6613+树DP)

题目链接 传送门 题意 给你一棵无根树,要你寻找一个根节点使得在将一条边权变为\(0\)后,离树根最远的点到根节点的距离最小. 思路 本题和求树的直径很像,不过要记得的东西有点多,且状态也很多. \(fi[u][0]\)表示在\(u\)这个结点不删边沿着子树方向能到达的最远距离,\(se[u][0]\)为第二远,\(th[u][0]\)为第三远,\(fa[u][0]\)表示沿着父亲方向能到达的最远距离,第二维为\(1\)表示删一条边能到达的距离. 不删边的转移和求树的直径转移方程基本上是一样的,