[JZOJ6089]【CodeChef 2014 April Challenge】Final Battle of Chef【数据结构】【整体二分】
Description
\(n,q,V\leq 100000,w_i\leq 10^9\)
Solution
又是一道大数据结构
由于有一个下取整,这就导致了不同时间的修改值是不能简单的直接加在一起的。
容易发现,1操作的影响只会影响到距离不超过log的点。
这样我们很容易得到一个\(q\log n\log ^2V\)的做法
同一深度的修改有一种套路是维护BFS序。
对于子树内的点,我们将log个深度对应的BFS序区间减去相应的影响。
对于修改点的log个有用的祖先,我们也类似操作,注意重复影响的要减去。
这样我们每次修改要修改\(log^2V\)段区间,用线段树维护又有一个log
由于每个点只会变负一次,我们只需要维护区间减得同时维护区间最小值,发现区间区间最小值变非正了就暴力走下去改,更新答案,这样每个点只会改一次,复杂度是有保证的。
虽然这样已经能通过这道题了(我怎么会说这跑的比log^2还快)
我们还要寻找更优秀的算法。
我们不妨先不修改子树,每次修改点只改祖先。记录\(tag_{i,j}\)表示点i对距离自己为\(j\)的儿子的影响
那么每次修改就变成了\(log^2\)的了,我们只需要对它的log的祖先,每一个改一下标记。
现在可以支持单点查询是否变非正,直接跳log级祖先查一下就好。
但我们要求某个时间的子树内非正点的个数,如果我们能快速算出每个点变非正的时间就好了。
可以整体二分/CDQ分治!
我们对于所有的操作按时间分治,对于分治区间\([l,r]\)记一个点集S,表示S中的点在时间[l,r]变非正,我们将出现时间在mid之前的所有操作都处理,一个个查询S中的点是否变非正,看是下放左区间还是右区间。
分析复杂度,每个点会查询log次,每次查询跳log个祖先,两个log
每个操作会用log次,每次时间log^2,这不可取!
我们发现如果每次都把操作暴力插回撤销,这非常的浪费。
因为我们总的需要查询的\(tag_{i,j}\)的改变次数只有$n\log^2 $
我们可以将\(tag\)数组可持久化,用一个链表或者vector存下每次改变的时间,查询的时候只需要移一下指针即可,容易看出指针的移动总次数只有\(n\log ^2\)
那么总的时间复杂度就降到了\(O(Q\log^2)\)
Code
//why always data structures ????
#include <bits/stdc++.h>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fod(i,a,b) for(int i=a;i>=b;--i)
#define N 100005
#define LL long long
using namespace std;
int fs[N],nt[2*N],dt[2*N],pr[N],n,m,w[N],dfw[N],sz[N],dfn[N],ans[N],m1,ask[N][3],f[N],dep[N];
LL sm[N];
//tree_array
int c[N];
int lowbit(int k)
{
return k&-k;
}
int get(int k)
{
int s=0;
while(k) s+=c[k],k-=lowbit(k);
return s;
}
void put(int k)
{
while(k<=n) c[k]++,k+=lowbit(k);
}
//prepare
void link(int x,int y)
{
nt[++m1]=fs[x];
dt[fs[x]=m1]=y;
}
void dfs(int k,int fa)
{
f[k]=fa;
dfw[dfn[k]=++dfn[0]]=k;
dep[k]=dep[fa]+1;
sz[k]=1;
for(int i=fs[k];i;i=nt[i])
{
int p=dt[i];
if(p!=fa) dfs(p,k),sz[k]+=sz[p];
}
}
//solve
struct node
{
LL v,t;
};
vector<node> tag[N][32];
int le[N][32],now[N][32],d[N],u1[N],u2[N],ts[N];
void ins(int k,int s,int ti)
{
if(!s||!k) return;
int v=s;
for(int c=0;v;c++)
{
int vl=(f[k])?v-(v>>2):v;
if(le[k][c]==0) tag[k][c].push_back((node){vl,ti});
else tag[k][c].push_back((node){vl+tag[k][c][le[k][c]-1].v,ti});
le[k][c]++;
v>>=1;
}
ins(f[k],s>>1,ti);
}
LL query(int k,int ti)
{
LL s=0;
for(int p=0;p<=31&&k;k=f[k],p++)
{
while(now[k][p]<le[k][p]-1&&tag[k][p][now[k][p]+1].t<=ti) now[k][p]++;
while(now[k][p]>0&&tag[k][p][now[k][p]].t>ti) now[k][p]--;
if(now[k][p]<le[k][p]&&tag[k][p][now[k][p]].t<=ti) s+=tag[k][p][now[k][p]].v;
}
return s;
}
void doit(int l,int r,int x,int y)
{
if(x>y) return;
if(l==r) {fo(i,x,y) ts[d[i]]=l;return;}
int mid=(l+r)>>1;
u1[0]=0,u2[0]=0;
fo(i,x,y)
{
if(pr[d[i]]<=query(d[i],mid)) u1[++u1[0]]=d[i];
else u2[++u2[0]]=d[i];
}
fo(j,1,u1[0]) d[x+j-1]=u1[j];
fo(j,1,u2[0]) d[x+u1[0]+j-1]=u2[j];
int md=x+u1[0]-1;
doit(l,mid,x,md);
doit(mid+1,r,md+1,y);
}
bool cmp(int x,int y)
{
return ts[x]<ts[y];
}
int main()
{
cin>>n;
fo(i,1,n) scanf("%d",&pr[i]);
fo(i,1,n-1)
{
int x,y;
scanf("%d%d",&x,&y);
link(x,y),link(y,x);
}
dfs(1,0);
int q;
cin>>q;
fo(i,1,q)
{
scanf("%d%d",&ask[i][0],&ask[i][1]);
if(ask[i][0]==1)
{
scanf("%d",&ask[i][2]);
ins(ask[i][1],ask[i][2],i);
}
}
fo(i,1,n) d[i]=i;
doit(1,q+1,1,n);
sort(d+1,d+n+1,cmp);
for(int i=1,j=1;i<=q;i++)
{
while(j<=n&&ts[d[j]]<=i) put(dfn[d[j]]),j++;
if(ask[i][0]==2) printf("%d\n",get(dfn[ask[i][1]]+sz[ask[i][1]]-1)-get(dfn[ask[i][1]]-1));
}
}
[JZOJ6089]【CodeChef 2014 April Challenge】Final Battle of Chef【数据结构】【整体二分】的更多相关文章
- Codechef April Challenge 2019 游记
Codechef April Challenge 2019 游记 Subtree Removal 题目大意: 一棵\(n(n\le10^5)\)个结点的有根树,每个结点有一个权值\(w_i(|w_i\ ...
- CF Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined)
1. Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) B. Batch Sort 暴力枚举,水 1.题意:n*m的数组, ...
- hdu 3986 Harry Potter and the Final Battle (最短路径)
Harry Potter and the Final Battle Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 65536/6553 ...
- CodeChef April Challenge 2019题解
传送门 \(Maximum\ Remaining\) 对于两个数\(a,b\),如果\(a=b\)没贡献,所以不妨假设\(a<b\),有\(a\%b=a\),而\(b\%a<a\).综上, ...
- Codechef April Challenge 2019 Division 2
Maximum Remaining 题意:给n个数,取出两个数$a_{i}$,$a_{j}$,求$a_{i}\% a_{j}$取模的最大值 直接排个序,第二大(严格的第二大)模第一大就是答案了. #i ...
- 【线段树 泰勒展开】Codechef April Challenge 2018 Chef at the Food Fair
第一次写泰勒展开:本地和CC差距好大 题目大意 大厨住的城市里办了一场美食节.一条街上开设了$N$个摊位,编号为$1∼N$.这天开始时,第$i$个摊位的食物会导致食物中毒的概率是$P_i$.在这一天中 ...
- 【CodeChef】December Challenge 2019 Div1 解题报告
点此进入比赛 这次比赛本来想好好打的,但不幸的是,这周先是要认真复习准备月考,考完又是发烧在床上躺了一个周末,所以最终没能打完. 我还是好弱啊. \(T1\):Binary XOR(点此看题面) 大致 ...
- Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined)D Dense Subsequence
传送门:D Dense Subsequence 题意:输入一个m,然后输入一个字符串,从字符串中取出一些字符组成一个串,要求满足:在任意长度为m的区间内都至少有一个字符被取到,找出所有可能性中字典序最 ...
- Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) B. Batch Sort
链接 题意:输入n,m,表示一个n行m列的矩阵,每一行数字都是1-m,顺序可能是乱的,每一行可以交换任意2个数的位置,并且可以交换任意2列的所有数 问是否可以使每一行严格递增 思路:暴力枚举所有可能的 ...
随机推荐
- Android 实现在Activity中操作刷新另外一个Activity数据列表
做android项目中遇到这样一个问题:有两个acticity,一个显示好友列表,另外一个显示会话列表,现在问题是在会话界面增加一个添加好友功能,添加好友后要求实时的刷新好友列表. 想了想,找了两种方 ...
- DataStage 错误集(持续更新)
DataStage 错误集(持续更新) DataStage序列文章 DataStage 一.安装 DataStage 二.InfoSphere Information Server进程的启动和停止 D ...
- XP+Android手机DIY家庭视频点播系统-历时3周全力打造吊丝的幸福生活
需求场景(纯熟虚构): 1. 哥电脑里有200G电影copy到手机上看没那么大空间,copy一部看一部删除一部,很是不方便也费时间. 2. 小林同学需求比较旺盛但是媳妇总有不方便的时候,家里有 ...
- UVa 10570 Meeting with Aliens (暴力)
题意:给定一个排列,每次可交换两个数,用最少的次数把它变成一个1~n的环状排列. 析:暴力题.很容易想到,把所有的情况都算一下,然后再选出次数最少的那一个,也就是说,我们把所有的可能的形成环状排列全算 ...
- 在VMware中设置CentOS7的网络
为了能够使用XShell来管理我们安装好的CentOS7系统,所以我们要先设置CentOS7的网络使其能够联网. 1.选择vmware的编辑,然后点击虚拟网络编辑器 2.点击更改设置(需要有 ...
- Linux 基础教程 41-系统关机和重启
在Linux系统中,仅仅是关机和重启相关的命令就至少有5个,shutdown. halt.poweroff.reboot.init.各个命令作用如下所示: 命令 说明 shutdown 可用于 ...
- Oracle FND API–Create User
--API - fnd_user_pkg.createuser----Example -- -- ---------------------------------------- API to CRE ...
- 菜鸟去重复之Sql
前言 本文主要是总结平时工作学习中遇到的使用Sql Server的去除重复的心得体会. 由于平时工作使用Sql并不多,此次在写本文的测试过程中,就遇到了问题,如能有幸得到高手点播,将不胜感激. 高手可 ...
- C# 调用Delphi dll
delphi dll 源码: library dllres; type char10 = ..] of char; TMydata = packed record id: Integer; name: ...
- 清除浏览器缓存meta标签
<meta http-equiv="Cache-Control" content="no-cache" /> <meta http-equiv ...