Codeforces Round #219 (Div. 2) E. Watching Fireworks is Fun
http://codeforces.com/contest/373/problem/E
4 seconds
256 megabytes
standard input
standard output
A festival will be held in a town's main street. There are n sections in the main street. The sections are numbered 1 through n from left to right. The distance between each adjacent sections is 1.
In the festival m fireworks will be launched. The i-th (1 ≤ i ≤ m) launching is on time ti at section ai. If you are at section x (1 ≤ x ≤ n) at the time of i-th launching, you'll gain happiness value bi - |ai - x| (note that the happiness value might be a negative value).
You can move up to d length units in a unit time interval, but it's prohibited to go out of the main street. Also you can be in an arbitrary section at initial time moment (time equals to 1), and want to maximize the sum of happiness that can be gained from watching fireworks. Find the maximum total happiness.
Note that two or more fireworks can be launched at the same time.
The first line contains three integers n, m, d (1 ≤ n ≤ 150000; 1 ≤ m ≤ 300; 1 ≤ d ≤ n).
Each of the next m lines contains integers ai, bi, ti (1 ≤ ai ≤ n; 1 ≤ bi ≤ 109; 1 ≤ ti ≤ 109). The i-th line contains description of the i-th launching.
It is guaranteed that the condition ti ≤ ti + 1 (1 ≤ i < m) will be satisfied.
Print a single integer — the maximum sum of happiness that you can gain from watching all the fireworks.
Please, do not write the %lld specifier to read or write 64-bit integers in C++. It is preferred to use the cin, cout streams or the %I64dspecifier.
50 3 1
49 1 1
26 1 4
6 1 10
-31
10 2 1
1 1000 4
9 1000 4
1992
题目分析:核心在如何减小∑|ai-x|
依然是长度不等的柱子,一时间顺序排列(ai),需要确定所有的xi,使得∑|ai-x|最小,当然两个xi之间需要可达。
这个问题确实很难,但是由于m=300,貌似暴力点是可以过的。n=150000。 【dp】
dp[i][j] 前i个柱子(ai),以xi=j为决策所能达到的最小的 ∑|ai-x|
dp复杂度是n*m=150000*300,而方程转移复杂度是O(n)
因此,需要减小方程转移的复杂度。转移集合D={dp[i-1][r] | r 和 j 可达},转移目标是求D的最小值。
可以发现转移集合D是连续的,r是连续的,因此问题变成了 求解区间最小值。
思路有二:
第一,线段树,每次将第i-1的数据放入一颗线段树,对于计算i 的时候,查询是log(n)【当然,此题修改和查询较简单,树状数组也可以实现最小值查询】
第二,单调队列,转移集合D只需要在j=1时求一次,以后j增加的时候,集合D最多只修改了两个元素。而建立一个递增的单调队列,维护待查询 区间的最小值。
思路1的复杂度较大,m*n*log(n),会T。但是叫一个小优化就过了。某些时候,最小值具有连续性,因此并不是每一次都需要去线段树里面查询。
思路2的解法比较常规,复杂度m*n。
下面是AC的代码,基于思路1+树状数组最小值查询+小优化。
#include<algorithm>
#include<iostream>
#include<fstream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<string>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<ctime> using namespace std;
#define FOR(i,a,b) for(int i=a;i<b;i++)
#define FORU(i,a,b) for(Uint i=a;i<b;i++)
#define FORD(i,a,b) for(int i=a;i>b;i--)
#define MST(a,num) memset(a,num,sizeof(a))
#define MCP(d,s) memcpy(d,s,sizeof(s))
#define WH(n) while(scanf("%d", &n) != EOF)
#define WHZ(n) while(scanf("%d", &n) != EOF && n != 0)
#define SCF(a) scanf("%d",&a)
#define SCFS(a) scanf("%s",a)
#define PRF(a) printf("%d",a)
#define PRS(a) printf("%s",a)
#define PRFF(a) printf("%d\n",a)
#define PRSF(a) printf("%s\n",a)
#define PRFFU(a) printf("%I64d\n",a) #define PI acos(-1)
#define min2(a,b) (a<b)?a:b
#define max2(a,b) (a>b)?a:b
#define max3(a,b,c) max(max(a,b),c)
#define max4(a,b,c,d) max(max(a,b),max(c,d)) #define FORE(e,x) for(__typeof(x.begin()) e=x.begin(); e!=x.end(); e++) //foreach(it, ans ) cout<<*it<<" ";
#define all(a) (a).begin(),(a).end() //sort(all(v));
#define len(a) ((int)(a).size())
#define pb push_back
#define mk make_pair
#define V(etype) vector<etype> typedef __int64 Uint;
typedef vector<int> Vint;
typedef pair<int,int>mypair; #define INF 0x3f3f3f3f
#define eps 1e-9
const int N=300000+100; int val[N];
int sum[N];
struct Bitree{
int n;//1 -> n
Bitree(int k){
n=1<<k;
clear();
}
void clear(){
FOR(i,1,n+1)sum[i]=val[i]=INF;
}
void add(int i,int _val){
val[i]=_val;
for(;i<=n;i+=-i&i)sum[i]=min(sum[i],_val);
}
bool cover(int i,int j)//whether i cover j,j<i
{
return j+(-i&i)>i;
}
int query(int j,int i){//[j,i]
int ret=INF;
for(;i>=j;){
if(cover(i,j)){ret=min(ret,val[i]);i--;}
else {ret=min(ret,sum[i]);i-=-i&i;}
}
return ret;
}
};
int dp[N];
int pos[N];
int b[N];
int t[N];
int main(){
int n,m,d;
Uint ret;
Bitree tree(18);
while(cin>>n>>m>>d){
FOR(i,0,m)scanf("%d%d%d",&pos[i],&b[i],&t[i]);
ret=0;
int tmp;
Uint ad;
FOR(j,1,n+1)dp[j]=abs(pos[0]-j);
FOR(i,1,m){
ad=(t[i]-t[i-1]);
ad*=d;
FORU(j,1,n+1){
if(j==1){
tree.clear();
FOR(r,1,n+1)tree.add(r,dp[r]);
tmp=tree.query(max2(1,j-ad),min2(n,j+ad));
}
else
if(j+ad <= n && val[j+ad]<=tmp)tmp=val[j+ad];
else
if(j-ad<=1 || val[j-ad - 1]>tmp);
else tmp=tree.query(max2(1,j-ad),min2(n,j+ad));
dp[j]=tmp+abs(pos[i]-j);
}
}
ret=INF;
FOR(j,1,n+1)ret=min2(ret,dp[j]);
ret=-ret;
FOR(i,0,m)ret+=b[i];
PRFFU(ret);
}
return 0;
}
Codeforces Round #219 (Div. 2) E. Watching Fireworks is Fun的更多相关文章
- Codeforces Round #219 (Div. 1) C. Watching Fireworks is Fun
C. Watching Fireworks is Fun time limit per test 4 seconds memory limit per test 256 megabytes input ...
- 数学 Codeforces Round #219 (Div. 2) B. Making Sequences is Fun
题目传送门 /* 数学:这题一直WA在13组上,看了数据才知道是计算cost时超long long了 另外不足一个区间的直接计算个数就可以了 */ #include <cstdio> #i ...
- Codeforces Round #219 (Div. 1)(完全)
戳我看题目 A:给你n个数,要求尽可能多的找出匹配,如果两个数匹配,则ai*2 <= aj 排序,从中间切断,分成相等的两半后,对于较大的那一半,从大到小遍历,对于每个数在左边那组找到最大的满足 ...
- Codeforces Round #219 (Div. 2) B. Making Sequences is Fun
B. Making Sequences is Fun time limit per test 2 seconds memory limit per test 256 megabytes input s ...
- Codeforces Round #219 (Div. 2) D. Counting Rectangles is Fun 四维前缀和
D. Counting Rectangles is Fun time limit per test 4 seconds memory limit per test 256 megabytes inpu ...
- Codeforces Round #219 (Div. 2) D题
D. Counting Rectangles is Fun time limit per test 4 seconds memory limit per test 256 megabytes inpu ...
- Codeforces Round #366 (Div. 2) ABC
Codeforces Round #366 (Div. 2) A I hate that I love that I hate it水题 #I hate that I love that I hate ...
- Codeforces Round #354 (Div. 2) ABCD
Codeforces Round #354 (Div. 2) Problems # Name A Nicholas and Permutation standard input/out ...
- Codeforces Round #368 (Div. 2)
直达–>Codeforces Round #368 (Div. 2) A Brain’s Photos 给你一个NxM的矩阵,一个字母代表一种颜色,如果有”C”,”M”,”Y”三种中任意一种就输 ...
随机推荐
- vagrant 设置除默认工项目之外的synced_folder一个坑
vagrant和host共享的目录,模式是以host主机目录为主,vagrant目录为从,所以记住当你新建同步目录的时候一定要先把vagratn目录文件备份一下,不然会被host目录覆盖
- express开发实例
express获取参数有三种方法:官网介绍如下 Checks route params (req.params), ex: /user/:id Checks query string params ( ...
- DataTable,DataSet,DataRow与DataView
DataTable和DataSet可以看做是数据容器,比如你查询数据库后得到一些结果,可以放到这种容器里,那你可能要问:我不用这种容器,自己读到变量或数组里也一样可以存起来啊,为什么用容器?原因是,这 ...
- 【ASP.NET】从服务器端注册客户端脚本
一.在Asp.net 服务端处理脚本,一般都用 ClientScriptManager ,即web窗体服务端的this.ClientScript.该对象比较常用的方法: 1.RegisterArray ...
- 总结iframe高度自适应,自适应子页面高度
在网上找了很多iframe的高度自适应,发现很多兼容性都不是很好,于是自己总结了一下. 页面html节点上要有 <!DOCTYPE html PUBLIC "-//W3C//DTD ...
- bzoj 3052: [wc2013]糖果公园 带修改莫队
3052: [wc2013]糖果公园 Time Limit: 250 Sec Memory Limit: 512 MBSubmit: 506 Solved: 189[Submit][Status] ...
- bzoj 3065: 带插入区间K小值 替罪羊树 && AC300
3065: 带插入区间K小值 Time Limit: 60 Sec Memory Limit: 512 MBSubmit: 1062 Solved: 253[Submit][Status] Des ...
- 在安全层面,企业如何获得更好的投资回报率 ROI?
前言 任何企业对投资都有回报的要求,回报可能是直接的「利润」,达到短期.长期的目标,或者通过投资减少损失.因此每个项目的决策者在每笔投资前都要衡量 ROI,证明该投资能达到的效果和收益,以便在项目结束 ...
- 使用 .NET 平台,如何玩转 Universal Windows 应用?
2015年7月30日 本文作者是 Managed Languages 团队项目经理 Lucian Wischik. 不久前,Visual Studio 2015上新增 Windows 10 应用的开发 ...
- [wikioi]关押罪犯
错误半天还是因为并查集写错了.写错的地方是合并X和Y的时候,应该把FX挂到FY上去,而不是把X挂到Y上或FY上去,因为FX和FY下面有一树别的节点. http://www.nocow.cn/index ...