loj6046 「雅礼集训 2017 Day8」爷
最近遇到几个分块题,我发现我一遇到分块题就死活构造不出来
不对,明明是,遇到数据结构题,就死活构造不出来。
所以我就找了几个分块题做做。
其实分块,树上的,很多都是先求一个dfs序,或者树剖,用一个log的代价或者没有多余的代价变成序列上的东西
树上的东西想到dfs序和树剖不是套路么……
很多不好维护的东西,都可以用分块来做,诶这不是我以前说过的么。
这道题,如果分块,那么按照套路,块内就可以排序,我们可以二分一个答案,然后在块内二分。
算了算复杂度,2个log,一个根号,不是很优秀的样子。
而题面上说$k \leq 10$,肯定有阴谋!
我们想,如果一个块内,元素最小最大值之差不大,我们就可以直接开个数组记录前缀和就好了,少一个log呢。
于是我们就,每次块内大小$>sz$或者最小值最大值之差$>S$,我们就新开一个块。
然后每隔一段时间重新分一下块,这样就非常优秀啦。
一开始自己智障,把$S$设得有点大,T掉了。
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<set>
using namespace std;
#define ll long long
#define db double
#define For(i,a,b) for(register int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(register int i=(a);i>=(b);--i)
const int maxn=2e5+7,maxt=1000+7,maxs=2e4+7,S=2e3,INF=0x3f3f3f3f;
int n,m,len,a[maxn],bel[maxn],sz;
int L[maxn],R[maxn]; char cc;ll ff;
template<typename T>void read(T& aa) {
aa=0;cc=getchar();ff=1;
while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
if(cc=='-') ff=-1,cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
aa*=ff;
} int fir[maxn],nxt[maxn],to[maxn],e=0,v[maxn];
void add(int x,int y,int z) {
to[++e]=y;nxt[e]=fir[x];fir[x]=e;v[e]=z;
} int dfn[maxn],fed[maxn],dfn_clock;
void dfs(int pos,int d) {
dfn[pos]=++dfn_clock;
a[dfn_clock]=d;
for(int y=fir[pos];y;y=nxt[y]) dfs(to[y],d+v[y]);
fed[pos]=dfn_clock;
} int sum[maxt][maxs],pl[maxt],pr[maxt],tot;
int d[maxn]; inline void pd(int x) {
if(!d[x]) return;
For(i,L[x],R[x]) a[i]+=d[x];
d[x]=0;
} inline void ud(int x) {
pl[x]=INF; pr[x]=-INF;
For(j,L[x],R[x]) {
pl[x]=min(pl[x],a[j]);
pr[x]=max(pr[x],a[j]);
}
For(j,0,pr[x]-pl[x]) sum[x][j]=0;
For(j,L[x],R[x]) ++sum[x][a[j]-pl[x]];
For(j,1,pr[x]-pl[x]) sum[x][j]+=sum[x][j-1];
} void bld() {
For(i,1,tot) pd(i);
int now=1,ld=INF,rd=-INF; L[1]=1;
For(i,1,n) {
ld=min(ld,a[i]); rd=max(rd,a[i]);
if(rd-ld>S||i-L[now]>=sz) {
R[now]=i-1;
L[++now]=i;
ld=rd=a[i];
}
R[bel[i]=now]=i;
}
tot=now;
For(i,1,tot) ud(i);
} inline int get_sum(int p,int x) {
if(x<pl[p]) return 0;
if(x>pr[p]) return sum[p][pr[p]-pl[p]];
return sum[p][x-pl[p]];
} inline int q(int ld,int rd,int x) {
int rs=0,lt=bel[ld],rt=bel[rd];
if(lt==rt) {
For(i,ld,rd) if(a[i]<=x) ++rs;
return rs;
}
if(ld!=L[lt]) {For(i,ld,R[lt]) if(a[i]<=x) ++rs;}
else rs+=get_sum(lt,x);
if(rd!=R[rt]) {For(i,L[rt],rd) if(a[i]<=x) ++rs;}
else rs+=get_sum(rt,x);
For(i,lt+1,rt-1) rs+=get_sum(i,x);
return rs;
} inline int Yth(int ld,int rd,int k) {
int lt=bel[ld],rt=bel[rd];
pd(lt); pd(rt);
if(rd-ld+1<k) return -1;
int l=INF,r=-INF,mid;
For(i,lt,rt) l=min(l,pl[i]),r=max(r,pr[i]);
if(l==r) return l; --l;
while(l<r-1) {
mid=(l+r)>>1;
if(q(ld,rd,mid)>=k) r=mid;
else l=mid;
}
return r;
} inline void chge(int ld,int rd,int x) {
int lt=bel[ld],rt=bel[rd];
if(lt==rt) {
pd(lt); For(i,ld,rd) a[i]+=x; ud(lt);
return;
}
if(ld!=L[lt]) {
pd(lt); For(i,ld,R[lt]) a[i]+=x; ud(lt);
}
else d[lt]+=x,pl[lt]+=x,pr[lt]+=x;
if(rd!=R[rt]) {
pd(rt); For(i,L[rt],rd) a[i]+=x; ud(rt);
}
else d[rt]+=x,pl[rt]+=x,pr[rt]+=x;
For(i,lt+1,rt-1) d[i]+=x,pl[i]+=x,pr[i]+=x;
} int main() {
read(n); read(m); read(len); sz=300;
int op,x,y;
For(i,2,n) {
read(x); read(y);
add(x,i,y);
}
dfs(1,0);
bld();
For(i,1,m) {
read(op); read(x); read(y);
if(op==1) printf("%d\n",Yth(dfn[x],fed[x],y));
else chge(dfn[x],fed[x],y);
if(i%1000==0) bld();
}
return 0;
}
loj6046 「雅礼集训 2017 Day8」爷的更多相关文章
- loj #6046. 「雅礼集训 2017 Day8」爷
#6046. 「雅礼集训 2017 Day8」爷 题目描述 如果你对山口丁和 G&P 没有兴趣,可以无视题目背景,因为你估计看不懂 …… 在第 63 回战车道全国高中生大赛中,军神西住美穗带领 ...
- LOJ#6046. 「雅礼集训 2017 Day8」爷(分块)
题面 传送门 题解 转化为\(dfs\)序之后就变成一个区间加,区间查询\(k\)小值的问题了,这显然只能分块了 然而我们分块之后需要在块内排序,然后二分\(k\)小值并在块内二分小于它的元素--一个 ...
- LOJ_6045_「雅礼集训 2017 Day8」价 _最小割
LOJ_6045_「雅礼集训 2017 Day8」价 _最小割 描述: 有$n$种减肥药,$n$种药材,每种减肥药有一些对应的药材和一个收益. 假设选择吃下$K$种减肥药,那么需要这$K$种减肥药包含 ...
- 【LYOI 212】「雅礼集训 2017 Day8」价(二分匹配+最大权闭合子图)
「雅礼集训 2017 Day8」价 内存限制: 512 MiB时间限制: 1000 ms 输入文件: z.in输出文件: z.out [分析] 蛤?一开始看错题了,但是也没有改,因为不会做. 一开 ...
- loj6045 「雅礼集训 2017 Day8」价
我们考虑最小割. 我一开始觉得是裸的最小割,就直接S到每个减肥药连up+p[i]的边,减肥药到药材连inf边,药材到T连up,然后得到了40分的好成绩. 之后我发现这是一个假的最小割,最小割割的是代价 ...
- [LOJ#6044]. 「雅礼集训 2017 Day8」共[二分图、prufer序列]
题意 题目链接 分析 钦定 \(k\) 个点作为深度为奇数的点,有 \(\binom{n-1}{k-1}\) 种方案. 将树黑白染色,这张完全二分图的生成树的个数就是我们钦定 \(k\) 个点之后合法 ...
- LOJ#6045. 「雅礼集训 2017 Day8」价(最小割)
题面 传送门 题解 首先先把所有权值取个相反数来求最大收益,因为最小收益很奇怪 然后建图如下:\(S\to\)药,容量\(\inf+p_i\),药\(\to\)药材,容量\(\inf\),药材\(\t ...
- LOJ#6044. 「雅礼集训 2017 Day8」共(Prufer序列)
题面 传送门 题解 答案就是\(S(n-k,k)\times {n-1\choose k-1}\) 其中\(S(n,m)\)表示左边\(n\)个点,右边\(m\)个点的完全二分图的生成树个数,它的值为 ...
- 【LOJ6045】「雅礼集训 2017 Day8」价(网络流)
点此看题面 大致题意: 有\(n\)种药,每种药有一个权值,且使用了若干种药材.让你选择若干种药,使得药的数量与所使用的药材并集大小相等,求最小权值总和. 网络流 \(hl666\):这种数据范围,一 ...
随机推荐
- 2019-5-29-Roslyn-让-VisualStudio-急速调试底层库方法
title author date CreateTime categories Roslyn 让 VisualStudio 急速调试底层库方法 lindexi 2019-5-29 20:2:9 +08 ...
- 通过ID获取元素 注:获取的元素是一个对象,如想对元素进行操作,我们要通过它的属性或方法。
通过ID获取元素 学过HTML/CSS样式,都知道,网页由标签将信息组织起来,而标签的id属性值是唯一的,就像是每人有一个身份证号一样,只要通过身份证号就可以找到相对应的人.那么在网页中,我们通过id ...
- Linux 运维日常排错
硬盘与IO df -Th #查看挂载和文件系统类型.检查是否有空间用满,是否有业务数据未使用独立分区? iostat -x 1 1. 检查iowait是否持续在15%以上,说明硬盘负载高. 2. ...
- thinkphp Mongo模型
Mongo模型是专门为Mongo数据库驱动而支持的Model扩展,如果需要操作Mongo数据库的话,自定义的模型类必须继承Think\Model\MongoModel. Mongo模型为操作Mongo ...
- sqlite3-入门日记4-实现C++类封装
一.前言: 今天试了下如何用C++类实现接口封装,感觉蛮好 .用于封装的类主要有两个,SQLiteStatement类和SQLiteWrapper类,是一个老外写的.我看了下源码,主要是对C接口进 ...
- 使用pageHelper分页查询,报sql语句错误
1.异常详情: 2.异常分析: (1)pageHelper分页大致流程: 配置默认的拦截器:pagehelper.PageInterceptor,对发送的查询语句进行拦截,拦截之后对原有的查询语句进 ...
- AFO之后……
先上游记:@ 据说有一种东西叫狗屁不通文章生成器:@
- linux 软件 手动添加至桌面或启动栏
1.创建软连接(也可以不用创建软连接,直接写绝对路径) sudo ln -s /opt/eclipse/eclipse /usr/bin/eclipse 2.创建desktop文件 sudo gedi ...
- opencv-Mat数据类型及位数总结
转自:http://blog.sina.com.cn/s/blog_662c7859010105za.html 在OpenCV里面,许多数据结构为了达到內存使用的最优化,通常都会用它最小上限的空间来分 ...
- 34 N皇后问题Ⅱ
原题网址:https://www.lintcode.com/zh-cn/old/problem/n-queens-ii/ 34. N皇后问题 II 描述 笔记 数据 评测 讨论区 根据n皇后问题, ...