Educational Codeforces Round 61 (Rated for Div. 2)-C. Painting the Fence 前缀和优化
题意就是给出多个区间,要求去掉两个区间,使得剩下的区间覆盖范围最大。
当然比赛的时候还是没能做出来,不得不佩服大佬的各种姿势。
当时我想的是用线段树维护区间和,然后用单点判0,维护区间间断个数。然后打到一半,就发现想法有问题。
这道题正解就是简单的前缀和,或者DP。
我为了更加深入理解,两种方法都试了试。
前缀和版本:
由于题目给的范围是5000,明显支持N^2,于是我们枚举去掉的两个,刚好满足,那么要如何才能O(1)的得到答案?
我们其实可以这样,我们知道它的总覆盖的数目,这是非常容易求出的。减去枚举的区间对答案的贡献即可。那么如何减去贡献,我们知道两个区间,可能有两种情况,一种是有交集部分,这一部分需要在交集区间上减去2次,而剩下的部分需要在剩下部分减去1次就行。
那么如果要对答案产生影响,答案就是
总覆盖区间=枚举区间交集部分刚好被覆盖两次+剩下交集为空的区间被覆盖一次的个数
考虑如何求被覆盖一次的个数,通过维护差分,求得每个点的被覆盖次数
枚举区间,就能求得每个区间,被覆盖次数为1的个数(不会有交集)。
那么如何求两个区间交集部分刚好被覆盖两次的值呢???
很简单,由于这个区间交集是不确定的。那么我们如何求呢?
我们已经知道每个点的覆盖次数。
那么我们可以知道刚好被覆盖两次的点,所在位置。
利用前缀和,和差分的思想,我们可以用一个新的前缀和数组,记录当前被覆盖的次数刚好被覆盖次数为1的位置。
然后求前缀和,这样我们就能快速的求出,[L,R]区间内,刚好为2的个数。
这样答案也出来了,注意枚举区间可能交集可能不存在,这样就不用算覆盖次数为2的个数。
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;
const int maxx = ;
int pre[][maxx];
struct node{
int l,r;
}a[maxx];
int main(){
int n,q,sum,ans;
while(~scanf("%d%d",&n,&q)){
ans=;
sum=;
memset(pre,,sizeof(pre));
for (int i=;i<=q;i++){
scanf("%d%d",&a[i].l,&a[i].r);
pre[][a[i].l]+=;
pre[][a[i].r+]-=;
}
for (int i=;i<=n;i++){
pre[][i]+=pre[][i-];//每个位置的情况
if (pre[][i])sum++;
}
for (int i=;i<=n;i++){
if (pre[][i]==)
pre[][i]++;//每个位置个数是否是2
}
for (int i=;i<=n;i++){
pre[][i]+=pre[][i-];//次数==2的前i项个数
}
for (int i=;i<=q;i++){
for (int j=a[i].l;j<=a[i].r;j++){
if (pre[][j]==){
pre[][i]++;//在第i个区间内部有多少个数为1的个数
}
}
}
for (int i=;i<=q;i++){
for (int j=i+;j<=q;j++){
int l=max(a[i].l,a[j].l);
int r=min(a[i].r,a[j].r);
int tmp=sum;
if (r>=l)
tmp-=(pre[][r]-pre[][l-]);
tmp-=(pre[][j]+pre[][i]);
ans=max(ans,tmp);
}
}
printf("%d\n",ans);
}
return ;
}
那么我们考虑DP做法。
这个DP和我前几天做的DP非常像。
我们可以构建这样DP
DP[i]代表,选到i位置,选择k个的最优解。用L[i]表示某个覆盖到i位置的区间,往左能覆盖的最小坐标
那么转移方程就是:
dp[j]=max(dp[L[j]-1]+j-L[j]+1,dp[j])
同时要是短的段落,能覆盖的个数是大于当前的,可以更新更长的段。
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define per(i,j,k) for(int i=j;i>=k;i--)
using namespace std;
const int maxx = +;
int dp[maxx];
int L[maxx];
int main()
{
int n,q,tmp,l,r;
while(~scanf("%d%d",&n,&q))
{
rep(i,,n)
{
L[i]=i+;
dp[i]=;
}
rep(i,,q)
{
scanf("%d%d",&l,&r);
rep(j,l,r)
{
L[j]=min(L[j],l);
}
}
// for (int i=1;i<=n;i++){
// printf("%d ",L[i]);
// }
// cout<<endl;
rep(i,,q-)
{
per(j,n,)
{
dp[j]=max(dp[L[j]-]+j-L[j]+,dp[j]);
}
rep(j,,n){
dp[j]=max(dp[j],dp[j-]);
}
}
printf("%d\n",dp[n]);
}
return ;
}
Educational Codeforces Round 61 (Rated for Div. 2)-C. Painting the Fence 前缀和优化的更多相关文章
- Educational Codeforces Round 73 (Rated for Div. 2) D. Make The Fence Great Again(DP)
链接: https://codeforces.com/contest/1221/problem/D 题意: You have a fence consisting of n vertical boar ...
- Educational Codeforces Round 61 (Rated for Div. 2) D,F题解
D. Stressful Training 题目链接:https://codeforces.com/contest/1132/problem/D 题意: 有n台电脑,每台电脑都有初始电量ai,也有一个 ...
- Educational Codeforces Round 61 (Rated for Div. 2) E 多重背包优化
https://codeforces.com/contest/1132/problem/E 题意 有8种物品,重量是1~8,每种数量是\(cnt[i]\)(1e16),问容量为W(1e18)的背包最多 ...
- Educational Codeforces Round 61 (Rated for Div. 2)
A. Regular Bracket Sequence 题意:给出四种括号的数量 (( )) () )( 问是否可以组成合法的序列(只能排序不能插在另外一个的中间) 思路: 条件一:一个或 n个) ...
- Educational Codeforces Round 61 (Rated for Div. 2) E. Knapsack
非常经典的dp题,因为1至8的最大公约数是840,任何一个数的和中840的倍数都是可以放在一起算的, 所以我只需要统计840*8的值(每个数字(1-8)的sum%840的总和),剩下都是840的倍数 ...
- Educational Codeforces Round 61 (Rated for Div. 2) G(线段树,单调栈)
#include<bits/stdc++.h>using namespace std;int st[1000007];int top;int s[1000007],t[1000007];i ...
- Educational Codeforces Round 61 (Rated for Div. 2)F(区间DP,思维,枚举)
#include<bits/stdc++.h>typedef long long ll;const int inf=0x3f3f3f3f;using namespace std;char ...
- Educational Codeforces Round 61 (Rated for Div. 2)D(二分,模拟,思维)
#include<bits/stdc++.h>using namespace std;typedef long long ll;int n,k;ll a[200007],b[200007] ...
- Educational Codeforces Round 55 (Rated for Div. 2) C. Multi-Subject Competition 【vector 预处理优化】
传送门:http://codeforces.com/contest/1082/problem/C C. Multi-Subject Competition time limit per test 2 ...
随机推荐
- ios的跨站脚本限制
概述 项目中碰到一个问题,就是在ios机上,用iframe内嵌的网页有时需要登录,有时候又不需要登录.查找了半天,终于发现是ios的跨站脚本限制导致的.这里就来介绍下跨站脚本限制,供以后开发时参考,相 ...
- win10下 anaconda 环境下python2和python3版本转换
在cmd的环境下,输入以下命令安装Python2.7的环境 conda create -n python27 python=2.7 anaconda 上面的代码创建了一个名为python27的pyth ...
- TabTopUnderLineLayout【自定义顶部选项卡(带下划线)】
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 自定义顶部选项卡布局LinearLayout类,实现带下划线样式的效果. 备注:如果配合Fragment的话,MainActivit ...
- 机器学习——XGBoost大杀器,XGBoost模型原理,XGBoost参数含义
0.随机森林的思考 随机森林的决策树是分别采样建立的,各个决策树之间是相对独立的.那么,在我们得到了第k-1棵决策树之后,能否通过现有的样本和决策树的信息, 对第m颗树的建立产生有益的影响呢?在随机森 ...
- MySQL系列--3.数据类型和连接查询
1.存储引擎 数据创建,查询,更新和删除操作都是通过数据引擎来进行的.不同的存储引擎存储限制不同,支持不同的索引机制等. 查询数据库支持的存储引擎 MySQL 5.7.2支持的存储引擎有:InnoDB ...
- SpringCloud系列——Bus 消息总线
前言 SpringCloud Bus使用轻量级消息代理将分布式系统的节点连接起来.然后可以使用此代理广播状态更改(例如配置更改)或其他管理指令.本文结合RabbitMQ+GitHub的Webhook实 ...
- 【带着canvas去流浪】(2)绘制折线图
目录 一. 任务说明 二. 重点提示 三. 示例代码 3.1 一般折线图 3.2 用贝塞尔曲线绘制平滑折线图 四. 大数据量场景 示例代码托管在:https://github.com/dashnowo ...
- C#工具:WPF分页
1.使用ItemsControl控件 <UserControl x:Class="SunCreate.Vipf.Client.UI.CityDoor.PageControl" ...
- 使用C#开发windows服务定时发消息到钉钉群_群组简单消息
前言:本提醒服务,是由C#语言开发的,主要由windows服务项目和winform项目组成,运行服务可实现功能:向钉钉自定义机器人群组里,定时,定次,推送多个自定义消息内容,并实现主要功能的日志记录. ...
- C#/VB.NET设置Excel表格背景色
在查看很多有复杂的数据的表格时,为了能够快速地找到所需要的数据组时,往往需要对该数据组进行分类,一个简单快速的方法就是对数据组所在的单元格填充背景颜色,这样就使得我们在阅读文件时能够直观的看到数据分类 ...