题意:有$n$个区间,把它们划分成若干段,如果一段$k$个区间的交长度$\geq2$,那么会产生$\binom k2$的贡献,最大化贡献

对每个$i$用单调栈预处理出$l_i$表示最小的$j$使得$j\cdots i$这些区间的交长度$\geq2$

设$f_i$表示前$i$个区间的答案,有$f_i=\max\limits_{j=l_i}^if_{j-1}+\binom{i-j+1}2$,直接线段树上维护凸壳已经可以做到$O(n\log n)$了,但我们有优秀线性做法

思路来源于这里的最后一段,orz人形自走题库yww

称$[l_i,i]$为“转移区间”

我们要说明存在一种划分$[1,n]$的方式使得每个转移区间都可以被拆成(划分出来的两个区间的后缀+前缀)

划分方法是这样的:一开始设切分点$j=0$,一遇到$l_i\gt j$就把$j$设为$i$

这样划分肯定不会有划分区间严格包含转移区间:如果包含,那么会更早切分

也不会有转移区间严格包含划分区间:因为$l_i$单调,所以会更迟切分

于是每个转移区间都被分成了划分区间的后缀+前缀,前缀可以边加入边更新答案

因为后缀能更新到的DP值都在下一个划分区间,所以在做完一整个划分区间时反着DP更新下一个划分区间的答案即可

特殊情况是转移区间就是划分区间的后缀,暴力就行

总时间复杂度$O(n)$

#include<stdio.h>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef double du;
const ll inf=9223372036854775807ll;
void fmax(ll&a,ll b){
	a<b?a=b:0;
}
struct line{
	int k;
	ll b;
	ll v(ll x){
		return k*x+b;
	}
};
du its(line a,line b){
	return(b.b-a.b)/(du)(a.k-b.k);
}
template<class t>bool gt(t a,t b){
	return a>b;
}
template<class t>bool lt(t a,t b){
	return a<b;
}
template<bool(*f)(int,int)>struct mq{
	int a[300010];
	int q[300010],h,t;
	mq(){
		h=1;
		t=0;
	}
	void push(int i){
		while(h<=t&&f(a[i],a[q[t]]))t--;
		q[++t]=i;
	}
	void pop(int i){
		if(q[h]==i)h++;
	}
	int v(){
		return a[q[h]];
	}
};
mq<gt>l;
mq<lt>r;
int li[300010];
bool cut[300010];
template<bool(*f)(du,du)>struct ms{
	line st[300010];
	int tp;
	void push(line v){
		while(tp>1&&f(its(v,st[tp]),its(st[tp],st[tp-1])))tp--;
		st[++tp]=v;
	}
	ll v(int x){
		if(!tp)return-inf;
		while(tp>1&&f(x,its(st[tp],st[tp-1])))tp--;
		return st[tp].v(x);
	}
};
ms<gt>pre;
ms<lt>suf;
ll f[300010];
line v[300010];
int main(){
	int n,i,j,k;
	scanf("%d",&n);
	j=1;
	for(i=1;i<=n;i++){
		scanf("%d%d",l.a+i,r.a+i);
		l.push(i);
		r.push(i);
		while(r.v()-l.v()<1){
			l.pop(j);
			r.pop(j);
			j++;
		}
		li[i]=j;
	}
	j=0;
	for(i=1;i<=n;i++){
		if(li[i]>j)cut[j=li[i]]=1;
	}
	cut[n]=1;
	for(i=1;i<=n;i++)f[i]=-inf;
	j=1;
	for(i=1;i<=n;i++){
		v[i]={-i,f[i-1]+((ll)i*i-i)/2};
		if(li[i]<=j){
			pre.push(v[i]);
			fmax(f[i],pre.v(i));
		}
		if(cut[i]){
			for(j=i;j>=li[i];j--)fmax(f[i],v[j].v(i));
			f[i]+=((ll)i*i+i)/2;
			pre.tp=0;
			if(i<n){
				suf.tp=0;
				for(j=i+1;!cut[j];j++);
				for(k=i;j>i;j--){
					while(k>=li[j])suf.push(v[k--]);
					fmax(f[j],suf.v(j));
				}
			}
			j=i+1;
		}else
			f[i]+=((ll)i*i+i)/2;
	}
	printf("%lld",f[n]);
}

[xsy3466]见面会的更多相关文章

  1. 编程之美 set 15 高效率地安排见面会

    题目 有 n 个学生分别对 m 个见面会感兴趣, 为了满足所有学生的要求, HR 希望每个学生都能参加自己感兴趣的所有见面会 思路 1. 假设某一个同学同时对k个小组感兴趣, 那么这k个小组两两之间都 ...

  2. 编程之美:1.9高效率安排见面会 图的m着色问题 回溯法

    原书问题,可以转换为图的m着色问题 ,下面该问题的代码 这里有参考ppt与code,免积分载 http://download.csdn.net/detail/u011467621/6341195 // ...

  3. 上海MVP见面会

    很愉快,很有收获的一次见面!

  4. 为什么你学过Java却忘光了——记第一次助教同学见面会

    大约两周之前,主讲老师刘志勇老师和我约定,让我上周四到课堂上和同学们认识.交流一下.一开始我不太明了去和大家见面要说些什么,也不太理解这么做的必要性是什么.但随着日子临近,我请教了周筠老师,周筠老师和 ...

  5. 2015游戏蛮牛——蛮牛杯第四届开发者大赛 创见VR未来开启报名

    蛮牛杯启动了,大家开始报名! http://cup.manew.com/ 这不是一篇普通的通稿,别着急忽略它.它是一篇可以让你梦想变现的通稿! 从某一天开始,游戏蛮牛就立志要为开发者服务,我们深知这一 ...

  6. 【转载学习前辈的经验】-- Mistakes I made (as a developer) 我(作为一名开发者)所犯过的错误

    我 2006 年开始工作,至今已经 10 年.10 年是个里程碑,我开始回顾自己曾经犯过的错误,以及我希望从同行那里得到什么类型的忠告.一切都在快速改变,10 年了,我不能确定这些秘诀是否还有用. 不 ...

  7. CSS+DIV 设计一个简单的个人网页界面

    *{ margin:0px; padding:0px; } body{ background:#e5e6d0; } #header,#menu,#banner,#main,#footer{ margi ...

  8. 个人阅读作业——M1/M2总结

    ~ http://www.cnblogs.com/wx1306/p/4831950.html 在这篇博客中,我提出来一些关于软件工程的问题,但随着这一个学期的即将结束,以及我对软件开发的了解的深入,我 ...

  9. TypeScript的全部资料,以后都放这儿了

    很早之前就听说TypeScript了(以下简称TS),但总是用难以抽出时间给自己找到这个冠冕堂皇的理由.最近又心血来潮,打算写TS的博客了,毕竟TS核心开发者也是C#之父,像我这么热爱C#的人,怎么可 ...

随机推荐

  1. margin-bottom无效问题以及div里内容动态居中样式!

    最近调前端样式时候,遇到一个需求,在中间文字不对等的情况下想让下面的操作文字距离底部对齐,如图: , 刚开始觉得使用margin-bottom就可以,后来发现只有margin-top是管用的,查了资料 ...

  2. 关于分布式存储系统中-CAP原则(CAP定理)与BASE理论比较

    CAP原则又称CAP定理,指的是在一个分布式系统中, Consistency(一致性). Availability(可用性).Partition tolerance(分区容错性),三者不可得兼. CA ...

  3. JavaScript 简单吗

    英文:Aurélien Hervé  译文:众成翻译/msmailcode 这里有一些 Javascript初学者应该知道的技巧和陷阱.如果你已经是专家了,顺便温习一下. Javascript也只不过 ...

  4. python网络编程--事件驱动模型

    论事件驱动与异步IO 事件驱动模型:根据事件的触发去干什么事,就是根据一个事件做反应 原文:http://www.cnblogs.com/alex3714/articles/5248247.html常 ...

  5. Python全局变量和局部变量

    全局变量和局部变量 定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域. 局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问.调用函数时,所有在函数内声明的变量 ...

  6. No.2 selenium学习之路之八种基本定位

    selenium的八种定位方式 1.通过id定位     find_element_by_id() send_keys() 输入框输入字符串 click()  鼠标点击事件 注:send_keys输入 ...

  7. Github中展示demo

    原文链接http://www.jianshu.com/p/75e30889e70a 第一步:找到Settings,点击 第二步:找到githubPages点击none,切换到master branch ...

  8. Java 从多层嵌套中访问内部类的成员

    一个内部类被嵌套多少层并不重要--它能透明地访问所有它能嵌入的外围类的所有成员 //: innerclasses/MultiNestingAccess.java // Nested classes c ...

  9. Unix IPC之Posix信号量实现生产者消费者

    采用多生产者,多消费者模型. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 /**  * 生产者  */ P(nempty); P(mutex); // 写入一个 ...

  10. Knockout.Js官网学习Demo(使用VS2012或者VS2013均可打开)

    https://pan.baidu.com/s/1gf9JZ8n#list/path=%2F