LOJ bitset+分块 大内存毒瘤题
题面
$ solution: $
真的没有想到可以用分块。
但是可以发现一个性质,每个询问只关心这个点最后一次赋值操作,和这个赋值操作后的所有取 $ min $ 操作。这个感觉很有用,但是真的很难让人想到低于 $ n\times m $ 的做法。基于 $ DAG $ 的数据结构是目前很少需要掌握的(好吧我都不知道有什么数据结构可以维护 $ DAG $ )所以肯定得骚操作。
我们可以发现一个 $ DAG $ 的性质,如果有一连串赋值操作我们可以根据拓扑序 $ O(n) $ 将所有操作完成,直接按顺序从后往前赋值,这样每个点赋值之后就不会再被访问。同理的, 如果有一连串取 $ min $ 操作我们也可以根据拓扑序 $ O(n) $ 将所有操作完成,直接 $ min $ 值从小到大取 $ min $, 这样每个点在取 $ min $ 之后就不会再被访问。但是当我们将这两种操作合到一起时就不行了。
但是联想一下上面说的性质:每个询问只关心这个点最后一次赋值操作,和这个赋值操作后的所有取 $ min $ 操作。我们可以搞出一个分块来,先预处理2操作,将2操作序列分块,并将每一块用上面的方法统计出每个结点在每个块内的取 $ min $ 后的值(初值inf)。然后我们就可以 $ \sqrt{n} $ 的求出任意一个区间里某个节点取 $ min $ 的最小值(其实还需要一个操作)。然后我们只需要快速找到每个询问的节点的最后一次赋值操作的编号,即赋值的大小,就可以得到答案。找到这个编号,我们可以对1操作分块来完成。
但是上述操作我们还需要知道一个东西,因为分块两边的小区间是要暴力遍历的,这个我们需要知道每个操作能否对某个点产生影响,这个等同于我们要知道 $ DAG $ 中一个点能否到另一个点。这个很奇妙的我们可以用 $ bitset $ 暴力完成。因为这个是无法用低于 $ n\times m $ 的复杂度完成,但是只涉及能否我们可以用二进制。
- 仔细分析求得答案需要什么关键信息
- 对于一连串操作可以一次完成,就考虑分治或分块
- 对于两种操作会互相影响,考虑先预处理一种操作在进行第二种操作
- 二进制和是与否,这个对于复杂度优化很好用。
- $ DAG $ 中的一些问题是难以用低于 $ n\times m $ 的做法完成的!
$ code: $
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#define ll long long
#define db double
#define rg register int
using namespace std;
int tt,t=1;
int n,m,q,ff;
int a[100005];
int idx[100005];
int fq[100005];
int fm[100005][404];
int vis[100005];
bitset<100005> f[100005];
struct su{
int to,next;
}b[200005];
int tou[100005];
struct pi{
int id,x,v,op;
inline bool operator <(const pi &i)const{
return v<i.v;
}
}s[100005],k[100005];
inline int qr(){
register char ch; register bool sign=0; rg res=0;
while(!isdigit(ch=getchar()))if(ch=='-')sign=1;
while(isdigit(ch))res=res*10+(ch^48),ch=getchar();
if(sign)return -res; else return res;
}
inline void yu(int i){ //预处理dag中两点是否可达
vis[i]=1; f[i][i]=1;
for(rg j=tou[i];j;j=b[j].next){
if(!vis[b[j].to]) yu(b[j].to);
f[i]|=f[b[j].to];
}
}
inline void dfs(int i,int v,int time,bool op){ //修改操作
if(vis[i]==t)return ; else vis[i]=t; //根据op判断是1操作还是2操作
if(op) a[i]=v,idx[i]=time; else fm[i][time]=v;
for(rg j=tou[i];j;j=b[j].next){
if(vis[b[j].to]==t)continue;
dfs(b[j].to,v,time,op);
}
}
int main(){
//freopen("dag.in","r",stdin);
//freopen("dag.out","w",stdout);
n=qr(); m=qr(); q=qr(); ff=sqrt(q-1)+1;
for(rg i=1;i<=q;++i) fq[i]=(i-1)/ff+1; //分块
for(rg i=1;i<=m;++i){
rg x=qr(),y=qr();
b[i]=su{y,tou[x]}; tou[x]=i;
}
for(rg i=1;i<=n;++i) if(!vis[i])yu(i);
for(rg i=1;i<=q;++i){ //先预处理每个块内的2操作
rg op=qr(); s[i]=pi{i,qr(),0,op};
if(op<=2) s[i].v=qr();
if(op==2) k[++tt]=s[i];
if(fq[i]!=fq[i+1]){
sort(k+1,k+tt+1); ++t; //从小到大,保证每个点只修改一次
for(rg j=1;j<=n;++j) fm[j][fq[i]]=1e9; //赋初值
for(rg j=1;j<=tt;++j)
dfs(k[j].x,k[j].v,fq[i],0);
tt=0;
}
}
for(rg i=1;i<=q;++i){
if(s[i].op==3){
rg x=s[i].x,y=idx[x],v=a[x],sf=0;
for(rg j=i;fq[j]==fq[i];--j){ //在同一个块内,暴力处理
if(s[j].op==1&&f[s[j].x][x]){ sf=1; y=j; v=s[j].v;
for(rg o=y;o<=i;++o)
if(s[o].op==2&&f[s[o].x][x]) v=min(v,s[o].v);
break;
}
}
if(!sf){ //这个if调了半个上午
for(rg j=y+1;fq[j]==fq[y];++j) //前小块
if(s[j].op==2&&f[s[j].x][x]) v=min(v,s[j].v);
for(rg j=fq[y]+1;j<=fq[i]-1;++j) v=min(v,fm[x][j]); //中间的大块
for(rg j=i;fq[j]==fq[i];--j) //后小块
if(s[j].op==2&&f[s[j].x][x]) v=min(v,s[j].v);
}
printf("%d\n",v);
}
if(fq[i]!=fq[i+1]){ ++t; //将这个块内的1操作一遍做完
for(rg j=i;fq[j]==fq[i];--j)
if(s[j].op==1)dfs(s[j].x,s[j].v,j,1);
}
}
return 0;
}
LOJ bitset+分块 大内存毒瘤题的更多相关文章
- 【卡常 bitset 分块】loj#6499. 「雅礼集训 2018 Day2」颜色
好不容易算着块大小,裸的分块才能过随机极限数据:然而这题在线的数据都竟然是构造的…… 题目描述 有 $n$ 个数字,第 $i$ 个数字为 $a_i$. 有 $m$ 次询问,每次给出 $k_i$ 个区间 ...
- [LOJ#114]k 大异或和
[LOJ#114]k 大异或和 试题描述 这是一道模板题. 给由 n 个数组成的一个可重集 S,每次给定一个数 k,求一个集合 T⊆S,使得集合 T 在 S 的所有非空子集的不同的异或和中,其异或和 ...
- PHP读写大“二进制”文件,不必申请很大内存(fopen、fread、fwrite、fclose)
<?php /** * 读写大二进制文件,不必申请很大内存 * 只有读取到内容才创建文件 * 保证目录可写 * * @param string $srcPath 源文件路径 * @param s ...
- 一个Java对象到底占用多大内存?
最近在读<深入理解Java虚拟机>,对Java对象的内存布局有了进一步的认识,于是脑子里自然而然就有一个很普通的问题,就是一个Java对象到底占用多大内存? 在网上搜到了一篇博客讲的非常好 ...
- JVM优化之调整大内存分页(LargePage)
转自:http://cjjwzs.iteye.com/blog/1059381 本文将从内存分页的原理,如何调整分页大小两节内容,向你阐述LargePage对JVM的性能有何提升作用,并在文末点明了大 ...
- (转)mongoDB 禁用大内存页面 transparent_hugepage=never
最近在学mongoDB,安装倒没什么困难,有yum仓库.不过接入ctl后的一条warning倒挺让人烦心的. 1 2 2015-03-22T09:27:00.222+0800 I CONTROL [ ...
- 一个Java对象到底占用多大内存
在网上搜到了一篇博客讲的非常好,里面提供的这个类也非常实用: import java.lang.instrument.Instrumentation; import java.lang.reflect ...
- mysql大内存高性能优化方案
mysql优化是一个相对来说比较重要的事情了,特别像对mysql读写比较多的网站就显得非常重要了,下面我们来介绍mysql大内存高性能优化方案 8G内存下MySQL的优化 按照下面的设置试试看:key ...
- Android 开发绕不过的坑:你的 Bitmap 究竟占多大内存?
0.写在前面 本文涉及到屏幕密度的讨论,这里先要搞清楚 DisplayMetrics 的两个变量,摘录官方文档的解释: density:The logical density of the displ ...
随机推荐
- MySQL表碎片清理
MySQL大表清理 生产环境data库业务表base_data大小:500G,data_free:31G mysql> SELECT table_schema,table_name,data_f ...
- 【洛谷T89359 扫雷】
题目链接 这个题有一个十分简单的做法 我们可以考虑位运算 按位异或(^) 异或,英文为exclusive OR,缩写成xor 异或(xor)是一个数学运算符.它应用于逻辑运算.异或的数学符号为“⊕”, ...
- DeepFaceLab报错,integer division or modulo by zero
DeepFaceLab的集成环境在众多换脸软件中是做的最好的.但是使用过程也会出现一些错误,主要的错误有两个,一个是你配置太低OOM了,主要体现显存太低.第二个是版本不对应.比如你原先用的cuda9. ...
- nw.js node-webkit基本程序结构与配置package.json配置说明
(一)基本程序结构 如上图,是一个nw程序的基本组织结构,在根目录下有package.json(程序的配置文件)和index.html(可以是任意名称,应用的启动页面):js/css/resource ...
- iOS应用将强制使用HTTPS安全加密-afn配置https(190926更新)
WWDC 2016苹果开发者大会上,苹果在讲解全新的iOS10中提到了数据安全这一方面,并且苹果宣布iOS应用将从2017年1月起启用名为App Transport Security的安全传输功能. ...
- C# .Net动态调用webService实现思路及代码
加载: using System; using System.Collections.Generic; using System.Linq; using System.Web; using Syste ...
- vue-loader分析
分析一下Vue2.0中的vue-loader是如何处理.vue单文件组件的: 1.vueLoaderplugin 作用是 找到.vue,.vue.html的rules然后在他们的rule里添加 pit ...
- robotframework之用户关键字的用法
robotframework是一个关键字驱动框架,核心在于关键字的应用 目录 1.如何创建用户关键字 2.调用用户关键字 3.用户关键字的使用场景 1.如何创建关键字 第一种:直接在项目上右键,添加用 ...
- 什么是SLF,PSL,MLF,SLO?
受国际经济金融形势不确定性增强以及各种影响流动性的因素波动较大影响,近年来我国银行体系短期流动性供求的波动性有所加大,尤其是当多个因素相互叠加或市场预期发生变化时,有可能出现市场短期资金供求缺口难以通 ...
- Elasticsearch如何关掉服务
1.使用head插件找到想关掉的节点进行关停 2.使用命令kill杀掉服务器的ES进程即可1.查找ES进程ps -ef | grep elastic 2.杀掉ES进程kill -9 2382(进程号) ...