Problem A

  内存限制 256MB 时间限制 5S
  程序文件名 A.pas/A.c/A.cpp
  输入文件 A.in 输出文件 A.out
  你有一片荒地,为了方便讨论,我们将这片荒地看成一条直线,这条直线被划分成n段(从左往右,依次标为1,2,3,...,n)。
  接下来的m年,你会开垦这片荒地并种植作物。不过每年的播种都会受到限制,如果你选择这一年播种,你必须将某段区间全部播种,并且也只能在这段区间播种。
  不过,荒地本身并不适合种植,所以你需要对土地花一定成本改良土质才能播种,而改良过的土地就不需要再次改良了。因此有时候播种可能不是很明智,你也可以选择这一年不播种。
  现在你想知道自己通过这m年种植最多能赚到多少钱。
输入
  第一行,两个整数 n,m 
  第二行,n个整数
  依次代表每段土地改良土质的花费(标号从1到n)
  接下来有m行,每行代表1年的播种情况(从第一年到第m年)
  每行有3个整数,l,r,p (1<=l<=r<=n)
  依次是这一年播种区间的左边界和右边界的编号,以及这次播种收获的作物能卖出的价钱
输出
  一行,一个整数,代表最大的利润
样例输入
  7 4
  3 2 3 2 1 2 3
  1 2 5
  2 3 5
  3 5 3
  7 7 5
样例输出
  4

数据范围
   30%  n,m<=100
   100%  n,m<=200000
   其他输入的整数均为不超过 1000 000 000 的正整数

  DP里面我就是最怕这样的题,在考场上由于用的是最大权闭合子图,根本没往DP方面想。而且这道题DP的优化也是我在用裸的DP编了一遍后才看出来的。注意到DP转移中只存在赋值,区间最值,区间加这几个操作,着表示可以用线段树整体维护。

  

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<string>
#include<queue>
#include<stack>
using namespace std;
#ifdef WIN32
#define LL "%I64d"
#else
#define LL "%lld"
#endif
#define MAXN 1100000
#define MAXM 1000000
#define MAXT 1000000
#define lch (now<<1)
#define rch (now<<1^1)
#define INFL 0x3f3f3f3f3f3f3f3fLL
#define PROB "A"
typedef long long qword;
struct aaa
{
int x,y,z;
}al[MAXM];
bool operator< (aaa a1,aaa a2)
{
return a1.x<a2.x||(a1.x==a2.x && a1.y<a2.y);
}
int n,m;
//qword f[MAXN];
int value[MAXN];
qword sum[MAXN];
//segment tree
struct node
{
int l,r;
qword val1,val2,lazy;
}tree[MAXT];
inline void up(int now)
{
if (tree[now].l==tree[now].r)return ;
tree[now].val1=max(tree[lch].val1,tree[rch].val1)+tree[now].lazy;
tree[now].val2=max(tree[lch].val2,tree[rch].val2)+tree[now].lazy;
}
inline void down(int now)
{
if (tree[now].l==tree[now].r)return ;
tree[lch].lazy+=tree[now].lazy;
tree[lch].val1+=tree[now].lazy;
tree[lch].val2+=tree[now].lazy;
tree[rch].lazy+=tree[now].lazy;
tree[rch].val1+=tree[now].lazy;
tree[rch].val2+=tree[now].lazy;
tree[now].lazy=;
}
void build_tree(int now,int l,int r)
{
tree[now].l=l;
tree[now].r=r;
tree[now].lazy=;
if (l==r)
{
tree[now].val1=-INFL;
tree[now].val2=-INFL;
if (!l)
{
tree[now].val1=tree[now].val2=;
}
return ;
}
build_tree(lch,l,(l+r)>>);
build_tree(rch,((l+r)>>)+,r);
up(now);
}
void set_val(int now,int pos,qword v,qword vnow)
{
if (tree[now].l==tree[now].r)
{
if (v>vnow+tree[now].val1)
{
tree[now].val1=v-vnow;
tree[now].val2=v-vnow+sum[tree[now].l];
}
return ;
}
if (pos<=(tree[now].l+tree[now].r)>>)
set_val(lch,pos,v,vnow+tree[now].lazy);
else
set_val(rch,pos,v,vnow+tree[now].lazy);
up(now);
}
qword get_val1(int now,int l,int r)
{
if (l>r)return -INFL;
if (tree[now].l==l && tree[now].r==r)
{
return tree[now].val1;
}
int mid=(tree[now].l+tree[now].r)>>;
if (r<=mid)
return get_val1(lch,l,r)+tree[now].lazy;
if (mid<l)
return get_val1(rch,l,r)+tree[now].lazy;
return max(get_val1(lch,l,mid),get_val1(rch,mid+,r))+tree[now].lazy;
}
qword get_val2(int now,int l,int r)
{
if (l>r)return -INFL;
if (tree[now].l==l && tree[now].r==r)
{
return tree[now].val2;
}
int mid=(tree[now].l+tree[now].r)>>;
if (r<=mid)
return get_val2(lch,l,r)+tree[now].lazy;
if (mid<l)
return get_val2(rch,l,r)+tree[now].lazy;
return max(get_val2(lch,l,mid),get_val2(rch,mid+,r))+tree[now].lazy;
}
void add_val(int now,int l,int r,qword v)
{
if (tree[now].l==l && tree[now].r==r)
{
tree[now].lazy+=v;
tree[now].val1+=v;
tree[now].val2+=v;
return ;
}
int mid=(tree[now].l+tree[now].r)>>;
down(now);
if (r<=mid)
{
add_val(lch,l,r,v);
return up(now);
}
if (mid<l)
{
add_val(rch,l,r,v);
return up(now);
}
add_val(lch,l,mid,v);
add_val(rch,mid+,r,v);
return up(now);
}
void scan(int now,qword vnow)
{
if (tree[now].l==tree[now].r)
{
printf("%lld ",vnow+tree[now].val1);
return ;
}
scan(lch,vnow+tree[now].lazy);
scan(rch,vnow+tree[now].lazy);
}
int main()
{
freopen(PROB".in","r",stdin);
// freopen("4.in","r",stdin);
freopen(PROB".out","w",stdout);
int i;
scanf("%d%d",&n,&m);
sum[]=;
for (i=;i<=n;i++)
{
scanf("%d",&value[i]);
sum[i]=sum[i-]+value[i];
}
int j;
for (i=;i<m;i++)
{
scanf("%d%d%d",&al[i].x,&al[i].y,&al[i].z);
}
sort(al,&al[m]);
/*for (i=0;i<m;i++)
{
for (j=al[i].y;j<=n;j++)
{
f[j]=max(f[j],f[j]+al[i].z);
}
for (j=al[i].x;j<al[i].y;j++)
{
f[al[i].y]=max(f[al[i].y],f[j]-(sum[al[i].y]-sum[j])+al[i].z);
}//f[j]+sum[j] -sum[al[u].y]+al[i].z
for (j=0;j<al[i].x;j++)
{
f[al[i].y]=max(f[al[i].y],f[j]-(sum[al[i].y]-sum[al[i].x-1])+al[i].z);
}
}*/
//for (i=1;i<=n+2;i++)f[i]=-INFL;
//f[0]=0;
build_tree(,,n);
for (i=;i<m;i++)
{
add_val(,al[i].y,n,al[i].z);
set_val(,al[i].y,get_val2(,al[i].x,al[i].y-)-sum[al[i].y]+al[i].z,);
set_val(,al[i].y,get_val1(,,al[i].x-)-(sum[al[i].y]-sum[al[i].x-])+al[i].z,);
//scan(1,0);printf("\n");
/* for (j=al[i].y;j<=n;j++)
{
f[j]=max(f[j],f[j]+al[i].z);
}
for (j=al[i].x;j<al[i].y;j++)
{
f[al[i].y]=max(f[al[i].y],f[j]-(sum[al[i].y]-sum[j])+al[i].z);
}//f[j]+sum[j] -sum[al[u].y]+al[i].z
for (j=0;j<al[i].x;j++)
{
f[al[i].y]=max(f[al[i].y],f[j]-(sum[al[i].y]-sum[al[i].x-1])+al[i].z);
}
for (j=0;j<=n;j++)
{
printf("%lld ",f[j]);
}printf("\n");*/
}
/*qword ans=0;
for (i=0;i<=n;i++)
{
printf("%d ",f[i]);
ans=max(ans,f[i]);
}*/
qword ans2=get_val1(,,n);
printf("%lld\n",ans2);
return ;
}

Contest20140906 ProblemA dp+线段树优化的更多相关文章

  1. [USACO2005][POJ3171]Cleaning Shifts(DP+线段树优化)

    题目:http://poj.org/problem?id=3171 题意:给你n个区间[a,b],每个区间都有一个费用c,要你用最小的费用覆盖区间[M,E] 分析:经典的区间覆盖问题,百度可以搜到这个 ...

  2. HDU4719-Oh My Holy FFF(DP线段树优化)

    Oh My Holy FFF Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) T ...

  3. UVA-1322 Minimizing Maximizer (DP+线段树优化)

    题目大意:给一个长度为n的区间,m条线段序列,找出这个序列的一个最短子序列,使得区间完全被覆盖. 题目分析:这道题不难想,定义状态dp(i)表示用前 i 条线段覆盖区间1~第 i 线段的右端点需要的最 ...

  4. zoj 3349 dp + 线段树优化

    题目:给出一个序列,找出一个最长的子序列,相邻的两个数的差在d以内. /* 线段树优化dp dp[i]表示前i个数的最长为多少,则dp[i]=max(dp[j]+1) abs(a[i]-a[j])&l ...

  5. 完美字符子串 单调队列预处理+DP线段树优化

    题意:有一个长度为n的字符串,每一位只会是p或j.你需要取出一个子串S(注意不是子序列),使得该子串不管是从左往右还是从右往左取,都保证每时每刻已取出的p的个数不小于j的个数.如果你的子串是最长的,那 ...

  6. POJ 3171.Cleaning Shifts-区间覆盖最小花费-dp+线段树优化(单点更新、区间查询最值)

    Cleaning Shifts Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4721   Accepted: 1593 D ...

  7. 题解 HDU 3698 Let the light guide us Dp + 线段树优化

    http://acm.hdu.edu.cn/showproblem.php?pid=3698 Let the light guide us Time Limit: 5000/2000 MS (Java ...

  8. 省选模拟赛 4.26 T1 dp 线段树优化dp

    LINK:T1 算是一道中档题 考试的时候脑残了 不仅没写优化 连暴力都打挂了. 容易发现一个性质 那就是同一格子不会被两种以上的颜色染.(颜色就三种. 通过这个性质就可以进行dp了.先按照左端点排序 ...

  9. 【uva1502/hdu4117-GRE Words】DP+线段树优化+AC自动机

    这题我的代码在hdu上AC,在uva上WA. 题意:按顺序输入n个串以及它的权值di,要求在其中选取一些串,前一个必须是后一个的子串.问d值的和最大是多少. (1≤n≤2×10^4 ,串的总长度< ...

随机推荐

  1. careercup-栈与队列 3.2

    3.2 请设计一个栈,除pop与push方法,还支持min方法,可返回栈元素中的最小值.push.pop和min三个方法的时间复杂度必须为O(1). 我们假设除了用一个栈s1来保存数据,还用另一个栈s ...

  2. Mysql 进阶操作

    将已经存在表设置自动增长属性alter table student change id id int not null auto_increment primary key;(注:这个地方一定是原来就 ...

  3. Memcache及telnent命令详解--转

    1.启动Memcache 常用参数memcached 1.4.3-p <num>      设置端口号(默认不设置为: 11211)-U <num>      UDP监听端口 ...

  4. 第二次装OA系统

    第二次安装:1.解压之后再MYOA目录下 找到一键安装.bat2.安装之后,一闪而过.(电脑上不需要apache,也不需要 mysql)3.192.168.1.111(自己电脑IP)看是否可以,若不可 ...

  5. thinking in java 读书笔记 --- overriding private method

    一个对象可以被用作它自身的类型或者是它的基类类型.当用作它的基类类型时叫做upcasting,如下所示 BaseClass ref = new DerivedClass()  //upcasting ...

  6. XC一键锁屏应用

    XC一键锁屏,一键Android锁屏应用,彻底解放开关机键~ 下载地址: http://download.csdn.net/detail/jczmdeveloper/7329447

  7. Android开发之意图解析

     android中意图(intent)就是告诉系统要做某件事情.比如要拨打电话或者发送短信. 或者在一个Activity中点击按钮跳转到另外一个activity时也用到意图.意图分为两种:显示意图和隐 ...

  8. PHP的无限栏目分类

    自己在PHP的无线栏目分类上面就是搞了很久都没有明白,所以现在是趁着记忆力还没有完全的消退的时候速度的记录下来 这里讲解的是最简单的树形栏目,适合的是小中型的栏目分类需求 1.这里讲解的是针对是只要通 ...

  9. FragmentTransaction.addToBackStack无效的问题

    FragmentTransaction.addToBackStack无效的问题: 如果当前的类继承的ActionBarActivity,则FragmentManager必须来自v4包,这样addToB ...

  10. 关于Androdi中SQLITE 3采用GBK编码存储,数据库中文乱码问题。

    1.最近开发一个项目,用SQLite Expert Personal打开数据库如下图,title会产生乱码,问题. 2.由于SQL lite默认是存储UTF-8格式,后来更改数据库编码类型为ANSI, ...