https://loj.ac/problem/6046

最近遇到几个分块题,我发现我一遇到分块题就死活构造不出来

不对,明明是,遇到数据结构题,就死活构造不出来。

所以我就找了几个分块题做做。

其实分块,树上的,很多都是先求一个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」爷的更多相关文章

  1. loj #6046. 「雅礼集训 2017 Day8」爷

    #6046. 「雅礼集训 2017 Day8」爷 题目描述 如果你对山口丁和 G&P 没有兴趣,可以无视题目背景,因为你估计看不懂 …… 在第 63 回战车道全国高中生大赛中,军神西住美穗带领 ...

  2. LOJ#6046. 「雅礼集训 2017 Day8」爷(分块)

    题面 传送门 题解 转化为\(dfs\)序之后就变成一个区间加,区间查询\(k\)小值的问题了,这显然只能分块了 然而我们分块之后需要在块内排序,然后二分\(k\)小值并在块内二分小于它的元素--一个 ...

  3. LOJ_6045_「雅礼集训 2017 Day8」价 _最小割

    LOJ_6045_「雅礼集训 2017 Day8」价 _最小割 描述: 有$n$种减肥药,$n$种药材,每种减肥药有一些对应的药材和一个收益. 假设选择吃下$K$种减肥药,那么需要这$K$种减肥药包含 ...

  4. 【LYOI 212】「雅礼集训 2017 Day8」价(二分匹配+最大权闭合子图)

    「雅礼集训 2017 Day8」价 内存限制: 512 MiB时间限制: 1000 ms 输入文件: z.in输出文件: z.out   [分析] 蛤?一开始看错题了,但是也没有改,因为不会做. 一开 ...

  5. loj6045 「雅礼集训 2017 Day8」价

    我们考虑最小割. 我一开始觉得是裸的最小割,就直接S到每个减肥药连up+p[i]的边,减肥药到药材连inf边,药材到T连up,然后得到了40分的好成绩. 之后我发现这是一个假的最小割,最小割割的是代价 ...

  6. [LOJ#6044]. 「雅礼集训 2017 Day8」共[二分图、prufer序列]

    题意 题目链接 分析 钦定 \(k\) 个点作为深度为奇数的点,有 \(\binom{n-1}{k-1}\) 种方案. 将树黑白染色,这张完全二分图的生成树的个数就是我们钦定 \(k\) 个点之后合法 ...

  7. LOJ#6045. 「雅礼集训 2017 Day8」价(最小割)

    题面 传送门 题解 首先先把所有权值取个相反数来求最大收益,因为最小收益很奇怪 然后建图如下:\(S\to\)药,容量\(\inf+p_i\),药\(\to\)药材,容量\(\inf\),药材\(\t ...

  8. LOJ#6044. 「雅礼集训 2017 Day8」共(Prufer序列)

    题面 传送门 题解 答案就是\(S(n-k,k)\times {n-1\choose k-1}\) 其中\(S(n,m)\)表示左边\(n\)个点,右边\(m\)个点的完全二分图的生成树个数,它的值为 ...

  9. 【LOJ6045】「雅礼集训 2017 Day8」价(网络流)

    点此看题面 大致题意: 有\(n\)种药,每种药有一个权值,且使用了若干种药材.让你选择若干种药,使得药的数量与所使用的药材并集大小相等,求最小权值总和. 网络流 \(hl666\):这种数据范围,一 ...

随机推荐

  1. Jquery 遍历 Table;遍历CheckBox ;遍历Select;全选/全不选

    关于Jquery:相信大家已经很熟悉了,我最近的项目运用到关于Jquery的遍历事件:权当总结下: 遍历Table <table  id="thistab"> < ...

  2. Java之实现多线程

    保证同步的几种方法: (1) 同步方法,synchronized 关键字修饰方法.由于Java中的每个对象都有一个内置锁,当用该关键词修饰时,内置锁会保护整个方法.在调用该方法前,需要获得内置锁,否则 ...

  3. linux nload命令简介及安装方法

    第一步:nload命令简介 nload 命令用于查看linux网络流量状况,实时输出.可以理解为是一个控制台应用程序,用来实时监测网络流量和带宽使用情况的命令. 使用可视化的界面显示流入和留出系统的网 ...

  4. scull 的内存使用

    scull 使用的内存区, 也称为一个设备, 长度可变. 你写的越多, 它增长越多; 通过使用 一个短文件覆盖设备来进行修整. scull 驱动引入 2 个核心函数来管理 Linux 内核中的内存. ...

  5. Error:(27, 13) Failed to resolve: com.android.support.constraint:constraint-layout:1.0.2约束布局constraint-layout导入失败的解决方案

    运行demo提示错误: Error:(27, 13) Failed to resolve: com.android.support.constraint:constraint-layout:1.0.2 ...

  6. [转]成为Java顶尖程序员 ,看这11本书就够了

    “学习的最好途径就是看书“,这是我自己学习并且小有了一定的积累之后的第一体会.个人认为看书有两点好处: 1.能出版出来的书一定是经过反复的思考.雕琢和审核的,因此从专业性的角度来说,一本好书的价值远超 ...

  7. 关于Mysql几周的整理文档

    https://files.cnblogs.com/files/swobble/mysql.rar 内容包括 版本测试(5.5,5.6,5.7) 平台测试(windows所有平台) 文件说明 精简说明 ...

  8. 一个Js开发者学习Python的第一天

    原文地址:小寒的博客 https://www.dodoblog.cn/blogs/5bf6b8fa0c09883d0f8aad13 作为一个有着足足两年半学习经验和一年半开发经验的js开发者,看着js ...

  9. Android基础控件ListView和自定义BaseAdapter适配器

    1.简介 ListView用于列表显示,相当于OC中的TableView,和适配器一块使用,相关属性: footerDividersEnabled:是否在footerView(表尾)前绘制一个分隔条, ...

  10. 黑裙辉DS918+安装错误码21,安装教程 重装需要重新制作启动盘

    不然报错误码21