免费的馅饼 HYSBZ - 2131 (树状数组维护二维偏序)

题目链接:https://cn.vjudge.net/problem/HYSBZ-2131

题目大意:中文题目

具体思路:对于任意的两个位置,posA和posB,我们可以如下推导。

|posA-posB|<=2*(tA-tB)

2*tB-2*tA<=posA-posB<=2*tB-2*tA.

2*tA+posA>=2*tB+posB  || 2*tA -pos A > = 2*tB-posB.(注意这个地方,只要有一个满足就可以了)

然后我们对2*tA+posA进行排序,每一次询问当当前能到达的最远的,这一段的最大值就可以了。

AC代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 # define ll long long
 4 const int maxn = 1e5+5;
 5 struct node
 6 {
 7     int w1,w2,val;
 8     bool friend operator < (node t1,node t2)
 9     {
10         if(t1.w1==t2.w1)
11             return t1.w2<t2.w2;
12         return t1.w1<t2.w1;
13     }
14 } q[maxn];
15 int a[maxn],ans[maxn],sz,c[maxn];
16 int lowbit(int t)
17 {
18     return t&(-t);
19 }
20 int query(int t)
21 {
22     int maxx=0;
23     for(int i=t; i; i-=lowbit(i))
24     {
25         maxx=max(maxx,c[i]);
26     }
27     return maxx;
28 }
29 void update(int pos,int val)
30 {
31     for(int i=pos; i<=sz; i+=lowbit(i))
32     {
33         c[i]=max(c[i],val);
34     }
35 }
36 int main()
37 {
38     int n,m,t,p;
39     scanf("%d %d",&n,&m);
40     for(int i=1; i<=m; i++)
41     {
42         scanf("%d %d %d",&t,&p,&q[i].val);
43         q[i].w1=2*t-p;
44         q[i].w2=2*t+p;
45     }
46     sort(q+1,q+m+1);
47     for(int i=1; i<=m; i++)
48     {
49         a[i]=q[i].w2;
50     }
51     sort(a+1,a+m+1);//注意离散化的时候要进行排序
52     sz=unique(a+1,a+m+1)-a-1;
53     for(int i=1; i<=m; i++)
54     {
55         q[i].w2=lower_bound(a+1,a+sz+1,q[i].w2)-a;
56         ans[i]=query(q[i].w2)+q[i].val;
57         update(q[i].w2,ans[i]);
58     }
59     int maxx=0;
60     for(int i=1; i<=m; i++)
61     {
62         maxx=max(maxx,ans[i]);
63     }
64     printf("%d\n",maxx);
65     return 0;
66 }

原文地址:https://www.cnblogs.com/letlifestop/p/10354638.html

时间: 2024-08-01 09:52:14

免费的馅饼 HYSBZ - 2131 (树状数组维护二维偏序)的相关文章

poj2481树状数组解二维偏序

按区间r降序排列,r相同按照l升序排列,两个区间相同时特判一下即可 /* 给定n个闭区间[l,r],如果对区间[li,ri],[lj,rj]来说, 有区间j严格包含(两个边界不能同时重合)在区间i内,那么区间i大于区间j 问区间有多少个区间大于区间i 读入所有的区间,按r降序,l升序 然后按顺序访问每个区间, */ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm>

poj 1195 二维树状数组 及二维树状数组模板

http://poj.org/problem?id=1195 求矩阵和的时候,下标弄错WA了一次... 求矩形(x1,y1) (x2,y2)的sum |sum=sum(x2,y2)-sum(x1-1,y2)-sum(x2,y1-1)+sum(x1-1,y1-1) 二维树状数组讲解:http://blog.csdn.net/u011026968/article/details/38532117 二维树状数组模板: /*========================================

[BZOJ4785][ZJOI2017]树状数组(概率+二维线段树)

4785: [Zjoi2017]树状数组 Time Limit: 40 Sec  Memory Limit: 512 MBSubmit: 297  Solved: 195[Submit][Status][Discuss] Description 漆黑的晚上,九条可怜躺在床上辗转反侧.难以入眠的她想起了若干年前她的一次悲惨的OI 比赛经历.那是一道 基础的树状数组题.给出一个长度为 n 的数组 A,初始值都为 0,接下来进行 m 次操作,操作有两种: 1 x,表示将 Ax 变成 (Ax + 1)

【树状数组】树状数组一维二维模板

以下模板都是点更新,区间查询,如果是区间更新点查询,只需将利用lowbit的循环方向倒过来 一维: inline int lowbit(int x) { return x & -x; } void add(int x, int val) { for(int i = x; i <= n; i += lowbit(i)) C[i] += val; } int sum(int x) { int ret = 0; for(int i = x; i > 0; i -= lowbit(i)) re

poj 2155- Matrix (树状数组,二维,更新区间,查询单点)

Matrix Time Limit:3000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Description Given an N*N matrix A, whose elements are either 0 or 1. A[i, j] means the number in the i-th row and j-th column. Initially we have A[i, j]

HDU 2642(树状数组模板二维)

Stars Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/65536 K (Java/Others) Total Submission(s): 1350    Accepted Submission(s): 554 Problem Description Yifenfei is a romantic guy and he likes to count the stars in the sky. To make the

树状数组_二维

class TreeArraryTwo{ public : const static int cmaxn = 1e3+200; int date[cmaxn][cmaxn]; int xsz, ysz; void init(int size_x, int size_y) { xsz = size_x; ysz = size_y; memset(date, 0, sizeof(date)); } inline int lowbit(int idx) { return idx & -idx; } v

SYSU-5, POJ 2131, 树状数组+二分

题目大意:给出n个人,顺序对位置进行请求,如果第i个人请求的位置上有人,则让这个人顺延,如果顺延的位置继续有人,递归进行,问最后所有人的位置. 解:这题貌似可以用平衡树+并查集搞定,但是我队友强烈安利树状数组的做法.赛场上没出,赛后结合discuz想了一下,作一下处理. 首先如果是一个请求第a[i]个有空位置的问题,那么这个问题显然可以用树状数组维护前缀和即可.所以我们现在考虑将原问题转化成这个问题. 考虑终态,把没有人的位置去掉,剩下的n个座位排在一起,显然转化成上面模型的形式 第i个询问时,

HDU 5869 Different GCD Subarray Query (GCD种类预处理+树状数组维护)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5869 问你l~r之间的连续序列的gcd种类. 首先固定右端点,预处理gcd不同尽量靠右的位置(此时gcd种类不超过loga[i]种). 预处理gcd如下代码,感觉真的有点巧妙... 1 for(int i = 1; i <= n; ++i) { 2 int x = a[i], y = i; 3 for(int j = 0; j < ans[i - 1].size(); ++j) { 4 int g