线段树
Love_xyh
这个作者很懒,什么都没留下…
展开
-
Atcoder ACL Beginner Contest
D.Flat Subsequencef[i]表示:数列最后一个为第i个的最大值,它可以由之前的,数值差绝对值在m以内的若干个f[j]转移而来。所以我们用一棵线段树,在a[j]的位置上把f[j]存下来,然后对于第i个值来说,只要查询:[max(a[i]-m,0),min(a[i]+m,300000)]区间内的最大f值即可。#include <bits/stdc++.h>using namespace std;const int N=3e5+5;int n,m,l,r,mid,ans;原创 2020-09-27 21:51:35 · 296 阅读 · 0 评论 -
[NOI2016]区间
我们只需要关注需要的线段中的最大值和最小值即可,所以若存在若干条不相关的线段,但长度在最小值与最大值之间,那么它不会对答案产生影响,所以我们把这样的不相关的线段全部放进去也没有任何关系。考虑可以用尺取法。按照线段长度排序后,设连续的一段线段的左右端点为i和j,根据两端点中的全部线段是否有至少m条拥有一个同样的点来移动i和j。如何判断两端点中的全部线段是否有至少m条拥有一个同样的点呢? 线段树进行区间累加并维护区间最大和。注意对坐标进行离散化。应该算是最套路的NOI题了吧…#include <原创 2020-09-21 20:28:14 · 131 阅读 · 0 评论 -
CF356A Knight Tournament
对m个操作倒序进行操作,利用线段树实现区间赋值。#include <bits/stdc++.h>using namespace std;const int N=3e5+5;int n,m;int l[N],r[N],x[N],sum[N<<2],add[N<<2],ans[N];inline void pushdown(int k){ if (add[k]) { sum[k<<1]=sum[k<<1|1]=add[k];原创 2020-09-21 20:10:15 · 171 阅读 · 0 评论 -
[CQOI2010]内部白点
画图后我们发现,新出现的黑点是不会再创造出更新的黑点的,即黑点只会被原有的黑点创造出一次。这样,此题就成了虔诚的墓主人,且不需要计算组合数问题。#include <bits/stdc++.h>#define int long longusing namespace std;const int N=1e5+5;int n,k,aa,bb,size,l,r,ans;int x[N],y[N],a[N],b[N],R[N],cnt[N],sum[N<<2];vector&l原创 2020-09-09 20:03:05 · 122 阅读 · 0 评论 -
[CTSC2018]混合果汁
为何要用整体二分,整体二分应该怎样二分,和[POI2011]MET-Meteors十分相像,这里就不再重复。我们现在只需要考虑如何判断每位顾客能否喝到满意的果汁即可。我们二分答案mid以后,将大于等于mid的用线段树维护。怎么维护呢 ?我们按价格建线段树,并在线段树中维护区间总份数,区间总价格这两个值。那么对于一个顾客来讲,如果当前的区间总份数小于他想要的份数,或者是区间最小价格大于他能接受的最大价格,就把该顾客划分到右区间,如若满足则划分到左区间。想要和[POI2011]MET-Meteors一样对原创 2020-08-05 19:06:33 · 449 阅读 · 0 评论 -
[ZJOI2013]K大数查询
区间求第k小,变为了区间求第k大。那么现在,对于插入数的结构体来说,如果q[i].k>mid,就把它划分到右区间,并进行单点累加;如果q[i].k<=mid,则划分到左区间。而对于查询的结构体来说,如果查询区间内的值,记为sum,当q[i].k>sum时,可知是由于mid不够小的缘故,所以应该把mid再变小写,即划分到左区间;当q[i].k<=sum时,说明mid已经够大了,所有划分到右区间。这里的划分,和求第k小相比,好像不是那么“显然”与“对称”了,所以需要注意。#incl原创 2020-08-05 18:27:44 · 144 阅读 · 0 评论 -
[SDOI2009]虔诚的墓主人
我们发现是对于每一个空位置,我们求出该空位置上下左右各有多少棵树后,该空位置的贡献就是 这四个方向上树的数量中选K棵出来的方案数的乘积。离散化之后对于答案没有任何影响,所以离散化。离散化后的点数为n^2,我们把行列拆开考虑。如果我们钦定某一行,我们发现,从左往右看,对于一段左右两棵树相同的连续空地,这段空地的每块空地,左右组合数的乘积是相同的,而每块空地上下组合数的乘积是不同的,所以可以考虑用某个东西来维护上下组合数的乘积,而对于左右组合数乘积,每行扫过去即可。(即,我们需要在每行扫过去的同时,维护每列的原创 2020-08-04 21:07:45 · 141 阅读 · 0 评论 -
BZOJ 1582: [Usaco2009 Hol]Holiday Painting 节日画画
发现列数只有15,那么建15棵线段树分开做即可。初始化时,注意ans(区间内贡献)与sum(区间内1个数)的区别。区间修改时,也需要根据v的值,进行分类讨论。#include <bits/stdc++.h>using namespace std;const int N=5e4+5;int n,m,q,l,r,ll,rr,v,now;int a[N][16],ans[16][N<<2],sum[16][N<<2],tag[16][N<<2];v原创 2020-06-10 00:30:21 · 144 阅读 · 0 评论 -
BZOJ 1645:[USACO07OPEN]City Horizon S
根据c从小到大排序,然后就无脑区间修改即可。由于l,r范围较大,所以就使用动态开点来做。没有考虑num[i].a=num[i].b的情况,对于这种特殊情况,数据中也不存在。#include <bits/stdc++.h>#define int long longusing namespace std;const int N=4e4+5;int n,cnt;int sum[...原创 2020-04-03 12:45:29 · 196 阅读 · 0 评论 -
CF580E Kefa and Watch
线段树维护哈希值。预处理一个数组,val[i][j]表示:全是i,长为j的哈希值。#include <bits/stdc++.h>#define int long longusing namespace std;const int N=1e5+5,base=131,MOD=1e9+7;int n,m,k,q;int a[N],sum[N<<2],tag[N&l...原创 2020-03-26 21:04:48 · 166 阅读 · 0 评论 -
CF515E Drazil and Park
化简一下公式:2h[a]+2h[b]+dis(a,b)=2h[a]+2h[b]+d[b]-d[a-1](d数组是一个距离前缀和)对于我们要求的一个区间,需要找的就是max((2h[b]+d[b])+(2h[a]-d[a-1]))而对于这个max,需要再维护一个最大左前缀和一个最大右后缀是不是和gss1很像#include <bits/stdc++.h>#define int ...原创 2020-03-26 21:03:22 · 193 阅读 · 1 评论 -
CF413E Maze 2D
对于一个区间,即2*len的一个矩阵,保存以下4个最小值:1.左上到右上的最短距离;2.左上到右下的最短距离;3.左下到右上的最短距离;4.左下到右下的最短距离。线段树维护即可。#include <bits/stdc++.h>using namespace std;const int N=2e5+5,inf=1e8;int n,q;char str[3][N];s...原创 2020-03-26 20:57:14 · 152 阅读 · 1 评论 -
CF786B Legacy
暴力建图m次,最多会出现nm条边。发现建图是对一个连续的区间进行操作,所以给每个区间一个新的编号,将一个区间看成是一个点来建图,即可做到“假的m条边”。而对于某些大的区间来说,由于可能询问的小的区间,所以我们需要在区间与区间之间再次连边,而区间内连边的最大条数为logn,m次则是mlogn。这个优化过程就是线段树优化建图。#include <bits/stdc++.h>#def...原创 2020-03-26 20:52:16 · 154 阅读 · 0 评论 -
BZOJ 3526: [Poi2014]Card
这题也可以用线段树来维护吗?好吧,是我菜了…ans[0/1][0/1]记录某一段:左端点是正面还是反面,右端点是正面还是反面,且这段是不是非降序列。合并的时候对于两端的四种情况和连接处的四种情况进行考虑即可。#include <bits/stdc++.h>using namespace std;//#define getchar() (p1==p2&&(p2...原创 2020-02-14 21:57:14 · 134 阅读 · 0 评论 -
线段树中的离散化——动态开点线段树
看到这两道题目(CF845C Two TVs,CF915E Physical Education Lessons),第一感觉都是可以离散化后用差分来做,细细想过后发现,差分的做法不适用于第二题,只能做第一题。为什么是这样呢?第一题中只需要求一个最大值是不是大于2,而这个最大值所在的位置一定是离散出来的某个点;而第二题中需要求的是个数,如果再通过简单的离散加差分,则不能这样进行统计了。所以就需要...原创 2020-02-11 20:37:00 · 347 阅读 · 0 评论 -
BZOJ 4552: [Tjoi2016&Heoi2016]排序
二分套线段树因为最后只要求一个位置上的数是多少,所以二分一下就好了,二分这个位置上的数的大小。如何判定呢?把每一个大于等于这个数的数都赋值为1,小于这个数的数赋值为0,然后对于升序降序操作,就是把区间内的0或1放置到区间前端或区间后端即可。修改完成后,判断那个位置的数值是0还是1即可,如果是1即说明符合了。如果是0即不符。稍微想一下可以大致理解这是有单调性的。#include <...原创 2020-01-20 23:28:03 · 121 阅读 · 0 评论 -
CF85D Sum of Medians
考虑一个离线做法暂时先不去考虑这个余3的限制,假设是求排序后前一半数的和,那么很明显,对于每一个add和del,将区间进行加,减修改,最后求一个类似query(1,1,n/2)的值即可。那么现在是求余3的和,也离线来做吧。对于add(x),就找到x的位置pos,将[pos,pos]区间累加上x,对于del(x),也是找到pos,将[pos,pos]区间累加上x。那么怎么求哪些数排完序后是余3...原创 2020-01-20 23:11:41 · 290 阅读 · 0 评论 -
POJ 2777 Count Color
一道很简单的线段树基础题。将一段区间修改为某种颜色,求一段区间内有多少种不同的颜色。考虑到颜色种类只有30种,所以就用一个二进制压位即可,将就要修改的区间修改为1<<(v-1),求某个区间内的颜色种类个数只要:ans|=sum[k<<1],ans|=sum[k<<1|1]。最后得到的答案转化为二进制后1的个数几位颜色种类个数。#include <i...原创 2020-01-20 22:17:06 · 90 阅读 · 0 评论 -
BZOJ 3626: [LNOI2014]LCA
帮助复习了树剖的基本操作。需要考虑一下lca最近公共祖先的最原始的性质,这样就可以来用树剖加线段树维护了。但是这样是个傻逼复杂度:nlognlogn*q,我们需要把q去掉,所以就离线做一遍,利用前缀和,差分一下即可。和gss2的离线思路差不多类似,可以算作一种套路吧。吐槽:一个晚上就做了一道题???我还是太菜了呀…明明有时间的,但是做完一题整个人就痿了???…#include <...原创 2020-01-17 23:07:34 · 141 阅读 · 0 评论 -
SP1557 GSS2 - Can you answer these queries II
琢磨了很久的一题,经过历史考试的思考,终于懂了。现在建立一个如下模型:sum[1]=a[1]+a[2]+a[3]+a[4]+…+a[i]sum[2]=a[2]+a[3]+a[4]+…+a[i]sum[3]=a[3]+a[4]+…+a[i]…sum[i]=a[i] (假设a[1]-a[i]均不等)然后,需要我们求[1,i]的最大子段和,这不就是求sum[1]-sum[i]的最大值吗?...原创 2020-01-10 22:18:48 · 196 阅读 · 4 评论 -
线段树——区间修改+查询(当前/历史)最大值模板
线段树的区间修改加查询区间最大值相信大家都熟悉了,但是,如何查询一个历史的最大值呢?此模板单纯是自己写写的,在oj上没有找到,是bzoj3064的弱化版,那题还有一个区间赋值的操作,更加麻烦。#include <bits/stdc++.h>using namespace std;const int N=1e5+5;int n,m,x,y,v;int a[N];char s...原创 2020-01-10 21:56:13 · 635 阅读 · 0 评论 -
SP1716 GSS3 - Can you answer these queries III
带修改的维护最大子段和,怎么维护呢?其实修改操作和原来的build操作是一模一样的。#include <bits/stdc++.h>using namespace std;const int N=5e4+5;int n,q,opt,x,y;int a[N];struct tree{int l,r,max,sum;}T[N<<2];void build(in...原创 2020-01-10 18:29:23 · 128 阅读 · 0 评论 -
SP1043 GSS1 - Can you answer these queries I
询问区间内最大连续子段和,维护一段区间的4个值即可。l:强制左端点选的最大子段和r:强制右端点选的最大子段和max:一段区间的最大子段和sum:一段区间的总和知道了需要维护哪些东西以后,怎么维护,就比较好想了。#include <bits/stdc++.h>using namespace std;const int N=5e4+5;int n,q,x,y;int a...原创 2020-01-10 18:28:08 · 115 阅读 · 0 评论 -
SP2713 GSS4 - Can you answer these queries IV
开方不能进行区间修改,只能很傻地进行单点修改,这不是稳T吗?但是我们发现,对于一个1e18范围内的数,开方后下取整,最多只要6次,就能变为1,也就是说,当一个区间全部都是1时,就不用再往下递归下去了。而把一个数,从1e18变为1,仅需要6logn的复杂度,所以时间复杂度为6nlogn,加上查询的复杂度,也仅为6(n+q)logn。#include <bits/stdc++.h>#d...原创 2020-01-10 18:25:11 · 138 阅读 · 0 评论 -
动态开点线段树 区间加,区间赋值,区间询问
个人感觉,动态开点线段树,就是在普通线段树上套一个开点操作。(就是把原来的#define中的lson和rson,换一下即可)区间加,区间询问#include <bits/stdc++.h>#define int long longusing namespace std;const int N=1e5+5;int n,m,x,y,v,now,cnt;int a[N],add...原创 2019-11-11 22:30:52 · 728 阅读 · 0 评论 -
线段树模板——区间赋值+区间询问最小值
#include <bits/stdc++.h>using namespace std;const int N=2e5+5;int n,m,opt,l,r,v,ans;int a[N],minn[N<<2],tag[N<<2];void build(int k,int l,int r){ if (l==r) { minn[k]=a[l];...原创 2019-11-07 22:11:55 · 401 阅读 · 0 评论