[雅礼集训 2017 Day2]水箱

2024-03-16 23:18
文章标签 day2 2017 集训 水箱 雅礼

本文主要是介绍[雅礼集训 2017 Day2]水箱,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

水箱

题解

其实还是蛮水的一道题。

我们很容易发现,如果全选没水的条件,一定是一组满足条件的解。关键是我们要如何选择有水的条件。

容易发现,对于一个有水条件,它一定会使包含它的一段连续区间内高度小于它的地方都有水。而在其区间内,没有它高的有水条件,当它满足时,一定也能被满足,而没有它高的无水条件,当它满足时,一定不能被满足。

我们先考虑如何求出这一段区间。这一段区间内一定不包含比当前水位置高的墙,我们可以用一棵线段树,在其前后位置的线段树上二分找出左右第一堵比它高的墙。时间复杂度为 O ( l o g n ) O(log\, n) O(logn)

之后对于这个区间,我们考虑如何维护在这个区间内的条件。我们可以开一棵vector的线段树,每个节点存储有多少个条件在当前节点对应的区间内。对于当前的有水操作求出其对应的不超过 l o g n log\, n logn的区间中有水条件比它矮的,我们可以根据二分来求出。而选择这个条件可以带来的贡献,是其导致成立的有水条件减去导致不成立的无水条件。

我们求出了每个有水条件对应的区间与贡献后,可以通过dp来求出最大的满足条件值。
总的时间复杂度为 O ( t n l o g n 2 ) O(tnlogn^2) O(tnlogn2)

源码

#include<bits/stdc++.h>
using namespace std;
#define MAXN 100005
typedef long long LL;
const int INF=1e8+10;
typedef pair<int,int> pii;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){_T f=1;x=0;char s=getchar();while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}x*=f;
}
int t,n,m,a[MAXN],maxx[MAXN<<2],ans[MAXN],answ,tot,dp[MAXN];
struct limite{int i,j,k;}q[MAXN];
struct tann{int fl,fr,ak;}s[MAXN];
struct ming{vector<int>lim,lzy;}tr[MAXN<<2];
bool cmp(int x,int y){return q[x].j<q[y].j;}
bool cmp1(tann x,tann y){return x.fr<y.fr;}
void build(int rt,int l,int r){tr[rt].lim.clear();tr[rt].lzy.clear();if(l==r)return (void)(maxx[rt]=a[l]);int mid=l+r>>1;build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);maxx[rt]=max(maxx[rt<<1],maxx[rt<<1|1]);
}
int queryL(int rt,int l,int r,int al,int ar,int aw){if(l>r||al>ar||r<al)return 0;if(al<=l&&r<=ar){if(maxx[rt]<=aw)return 0;if(l==r)return l;int mid=l+r>>1;if(maxx[rt<<1|1]<=aw)return queryL(rt<<1,l,mid,al,ar,aw);return queryL(rt<<1|1,mid+1,r,al,ar,aw);}int mid=l+r>>1,res=0;if(al<=mid)res=max(queryL(rt<<1,l,mid,al,ar,aw),res);if(ar>mid)res=max(queryL(rt<<1|1,mid+1,r,al,ar,aw),res);return res;
}
int queryR(int rt,int l,int r,int al,int ar,int aw){if(l>r||al>ar||r<al)return n;if(al<=l&&r<=ar){if(maxx[rt]<=aw)return n;if(l==r)return l;int mid=l+r>>1;if(maxx[rt<<1]<=aw)return queryR(rt<<1|1,mid+1,r,al,ar,aw);return queryR(rt<<1,l,mid,al,ar,aw);}int mid=l+r>>1,res=n;if(al<=mid)res=min(queryR(rt<<1,l,mid,al,ar,aw),res);if(ar>mid)res=min(queryR(rt<<1|1,mid+1,r,al,ar,aw),res);return res;
}
void Insert(int rt,int l,int r,int ai,int aw){if(l>ai||r<ai||l>r)return ;int mid=l+r>>1;if(q[aw].k==0)tr[rt].lim.push_back(aw);if(q[aw].k==1)tr[rt].lzy.push_back(aw);//printf("%d Insert in %d %d\n",aw,l,r);if(l==r)return ;if(ai<=mid)Insert(rt<<1,l,mid,ai,aw);if(mid<ai)Insert(rt<<1|1,mid+1,r,ai,aw);
}
void Sorted(int rt,int l,int r){sort(tr[rt].lzy.begin(),tr[rt].lzy.end(),cmp);sort(tr[rt].lim.begin(),tr[rt].lim.end(),cmp);if(l==r)return ;int mid=l+r>>1;Sorted(rt<<1,l,mid);Sorted(rt<<1|1,mid+1,r);
}
void Modify(int rt,int l,int r,int al,int ar,int ai){if(l>r||al>r||ar<l)return ;if(al<=l&&r<=ar){int L=0,R=tr[rt].lim.size()-1,num=-1;while(L<=R){int mid=L+R>>1;if(q[tr[rt].lim[mid]].j<=q[ai].j)L=mid+1,num=mid;else R=mid-1;}ans[ai]+=num+1;//printf("%d %d %d:%d ",ai,l,r,num+1);L=0;R=tr[rt].lzy.size()-1;num=-1;while(L<=R){int mid=L+R>>1;if(q[tr[rt].lzy[mid]].j<=q[ai].j)L=mid+1,num=mid;else R=mid-1;}ans[ai]-=num+1;//printf("%d %d\n",num+1,tr[rt].lzy.size());return ;}int mid=l+r>>1;if(al<=mid)Modify(rt<<1,l,mid,al,ar,ai);if(ar>mid)Modify(rt<<1|1,mid+1,r,al,ar,ai);
}
signed main(){freopen("tank.in","r",stdin);freopen("tank.out","w",stdout);read(t);while(t--){read(n);read(m);for(int i=1;i<n;i++)read(a[i]);build(1,1,n);answ=0;tot=0;for(int i=1;i<=m;i++){read(q[i].i);read(q[i].j);read(q[i].k);Insert(1,1,n,q[i].i,i);if(!q[i].k)answ++;}Sorted(1,1,n);for(int i=1;i<=m;i++)if(q[i].k==1){int al=queryL(1,1,n,1,q[i].i-1,q[i].j)+1;int ar=queryR(1,1,n,q[i].i,n,q[i].j);ans[i]=0;Modify(1,1,n,al,ar,i);s[++tot]=(tann){al,ar,ans[i]};//printf("%d %d:%d\n",al,ar,ans[i]);}sort(s+1,s+tot+1,cmp1);int k=0;dp[0]=answ;for(int i=1;i<=n;i++){dp[i]=dp[i-1];while(k<tot&&s[k+1].fr==i)k++,dp[i]=max(dp[i],dp[s[k].fl-1]-s[k].ak);//printf("DP%d:%d\n",i,dp[i]);}printf("%d\n",dp[n]);for(int i=0;i<=n;i++)dp[i]=0;}return 0;
}

谢谢

这篇关于[雅礼集训 2017 Day2]水箱的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/817058

相关文章

Java预备知识 - day2

1.IDEA的简单使用与介绍 1.1 IDEA的项目工程介绍 Day2_0904:项目名称 E:\0_code\Day2_0904:表示当前项目所在路径 .idea:idea软件自动生成的文件夹,最好不要动 src:src==sourse→源,我们的源代码就放在这个文件夹之内 Day2_0904.iml:也是自动生成的文件,不要动 External Libraries:外部库 我这

2014暑假集训搜索专题

A - 漫步校园 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit Status Description LL最近沉迷于AC不能自拔,每天寝室、机房两点一线。由于长时间坐在电脑边,缺乏运动。他决定充分利用每次从寝室到机房的时间,在校园里散散步。整个HDU校园呈方形布局,可划

2017 版本的 WebStorm 永久破解

1.  在IntelliJ官网中下载 最新版本的WebStorm   下载地址:https://www.jetbrains.com/webstorm/download/#section=windows 2. 获取注册码    获取地址:http://idea.lanyus.com/   点击获取注册码,然后将注册码复制,再打开最新版的WebStorm,将注册码粘贴到激活框中就大功告

【为项目做准备】Linux操作系统day2

这两天学校的事情总压着,day2拖了好几天..day2内容是进程数据结构 进程数据结构信号处理任务状态进程调度运行统计信息进程亲缘关系进程权限用户和组标识符(IDs)linux capabilities 内存管理文件与文件系统用户态与内核态用户态与内核态的转换函数调用栈内核栈和task_struct的关系 进程数据结构 进程or线程,在内核中,统一叫任务(Task),由一个统

Android智能家居实训day2

设置使用的布局文件 setContentView(R.layout.filename);,之后使用布局嵌套,一个布局内部可以嵌套另一个布局,内部的布局相当于外部布局的一个子控件,可以把它当作一个整体来操作,例如在今天的八宫格使用布局嵌套的时候,每一个格子是一个线性布局布局内使用垂直方向,而每两个布局作为一行,一共四行,这样就再拿一个布局框起来使用水平方向最后再把这四个布局用垂直方向。在布局之间分配

寒假集训第二天——线性表

现在时间是北京时间1点23分,第二天集训。。。 昨天花了老长时间把线性表看了下,表示很有压力,不大会用。。。 先说下我学到的线性表的皮毛。。。 首先是链表的构建,构建有两种方式: 顺序链表(尾插法建单链表) #include<stdio.h>struct node{int date;struct node *next;};int main(){int i,n;node *he

寒假集训第一天——结构体

期待已久的寒假集训终于开始了,第一天讲的内容比较简单——结构体,之前就学了点。。。 表示普通的结构体会用,涉及到指针都不大会,今天算是学了点指针的用法。。。 作业描述如下: 结构体 今天作业  1.定义一个acmer结构体,包括以下信息:姓名,学号,手机号,做题数,出生日期,其中出生日期date也是一个结构体,包括年、月、日  2.建立结构体数组,实现对多个同学

寒假集训——字典树(模板)

struct node{int v;node *next[26];} T[1000000];int t=0;node *newnode(){node *p=new node;//动态分配//node *p=&T[t++];//静态分配p->v=0;for(int i=0; i<26; i++)p->next[i]=NULL;return p;}void insertnode(node

寒假集训——二叉树

#include <iostream>#include <stdio.h>#include <string.h>#include <queue>using namespace std;typedef struct node{char date;node *lch,*rch;}Bn,*Bt;void cbtree(Bt &T)//先序建二叉树{char c;scanf("%c"

网易2017秋招编程题集合--完全解析

前言 一些大公司的真题里面总有些含金量很高的几个题,网易2017秋招编程题集合里面也有几个题是非常好的,比如说第三题跳石板,第四题黑暗的字符串都是很好的题目。特别是第四题的那种思路之前几乎完全没有接触过,还有第六题最大的奇约数里面还有部分数学思维在里面。 1.回文序列 题目描述:如果一个数字序列逆置之后跟原序列是一样的就称这样的数字序列为回文序列。例如: {1, 2, 1}, {15, 7