Description

给出一张四连通网格图,其中有 \(n\) 个点是连通的,维护以下两种操作:

1.把某个点变黑

2.给出一个白点,查询离这个白点最近的黑点的距离

题面

Solution

我们把每一行看作一个节点,建立一棵树

然后点分治维护这两个操作即可

实际上就是动态加入黑点,查询离某个点最近的黑点

唯一的区别在于:

走到这个节点之后还会在这个节点所代表的行里面走,设查询的为 \(x\),某个黑点为 \(u\)

要求: \(min(dis[u]+dis[x]+|y_u-y_x|)\)

\(dis[i]\) 表示从 \(i\) 出发走到这个重心所代表的行的最短路,\(y_i\) 表示走最短路碰到这个节点所代表的行的纵坐标

两者都可以从重心 \(bfs\) 求出

然后对于每一个重心维护数状数组查询 \(min(dis[u]+dis[x]+|y_u-y_x|)\)

把绝对值拆掉,用两个树状数组维护就行了,分别对应前后缀查询

值得注意的是:

这题的重心要是带权重心,否则预处理就会 \(TLE\)

#include<bits/stdc++.h>
#define pb push_back
using namespace std;
const int N=3e5+10,M=22,inf=1e9;
int n,m=0,tt=0,cnt=0,b[N],s[N],Lx[N],Ly[N],fa[N];
vector<int>S[N],G[N],E[N];
map<int,int>id[N];
inline void priwork(){
for(int i=1;i<=m;i++){
if(S[i].empty())continue;
sort(S[i].begin(),S[i].end());
for(int j=0,si=S[i].size(),x,k=0;j<si;j++){
x=S[i][j];id[i][x]=++tt;
if(j && S[i][j-1]+1==x)G[tt].pb(tt-1),G[tt-1].pb(tt);
else ++cnt,Lx[cnt]=i,Ly[cnt]=j;
b[tt]=cnt;s[cnt]++;
while(k<(int)S[i-1].size() && S[i-1][k]<x)k++;
if(k<(int)S[i-1].size() && S[i-1][k]==x){
E[b[id[i-1][x]]].pb(cnt),E[cnt].pb(b[id[i-1][x]]);
G[id[i-1][x]].pb(tt),G[tt].pb(id[i-1][x]);
}
}
}
for(int i=1;i<=n;i++){
sort(E[i].begin(),E[i].end());
E[i].erase(unique(E[i].begin(),E[i].end()),E[i].end());
}
}
int son[N]={inf},sz[N],rt=0,sum,p[N][M],dis[N][M];bool vis[N];
inline void getroot(int x,int last){
sz[x]=s[x];son[x]=0;
for(int i=E[x].size()-1;i>=0;i--){
int u=E[x][i];
if(u==last || vis[u])continue;
getroot(u,x);sz[x]+=sz[u];son[x]=max(son[x],sz[u]);
}
son[x]=max(son[x],sum-sz[x]);
if(son[x]<son[rt])rt=x;
}
vector<int>t1[N],t2[N];int dep[N];
inline void add1(int o,int x,int t){
for(int i=x;i<=s[o];i+=(i&(-i)))t1[o][i]=min(t1[o][i],t);
}
inline int qry1(int o,int x){
int ret=inf;
for(int i=x;i>=1;i-=(i&(-i)))ret=min(ret,t1[o][i]);
return ret;
}
inline void add2(int o,int x,int t){
for(int i=x;i>=1;i-=(i&(-i)))t2[o][i]=min(t2[o][i],t);
}
inline int qry2(int o,int x){
int ret=inf;
for(int i=x;i<=s[o];i+=(i&(-i)))ret=min(ret,t2[o][i]);
return ret;
}
inline void build(int x,int d){
queue<int>Q;
for(int i=Ly[x],u;i<Ly[x]+s[x];i++){
u=id[Lx[x]][S[Lx[x]][i]];
p[u][d]=i-Ly[x]+1;dis[u][d]=0;Q.push(u);
}
while(!Q.empty()){
int x=Q.front();Q.pop();
for(int i=G[x].size()-1;i>=0;i--){
int u=G[x][i];
if(vis[b[u]] || p[u][d])continue;
p[u][d]=p[x][d],dis[u][d]=dis[x][d]+1,Q.push(u);
}
}
for(int i=0;i<=s[x];i++)t1[x].pb(inf),t2[x].pb(inf);
}
inline void solve(int x,int d){
vis[x]=1;dep[x]=d;build(x,d);
for(int i=E[x].size()-1;i>=0;i--){
int u=E[x][i];if(vis[u])continue;
rt=0;sum=sz[u];getroot(u,x);
fa[rt]=x;solve(rt,d+1);
}
}
inline void Modify(int y){
int x=b[y],d;
while(x){
d=dep[x];
add1(x,p[y][d],dis[y][d]-p[y][d]);
add2(x,p[y][d],dis[y][d]+p[y][d]);
x=fa[x];
}
}
inline int query(int y){
int ret=inf,d,x=b[y];
while(x){
d=dep[x];
ret=min(ret,dis[y][d]+p[y][d]+qry1(x,p[y][d]));
ret=min(ret,dis[y][d]-p[y][d]+qry2(x,p[y][d]));
x=fa[x];
}
if(ret<N)return ret;
return -1;
}
int main(){
int x,y,Q,op;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d%d",&x,&y);
m=max(x,m);S[x].pb(y);
}
priwork();
rt=0;sum=n;getroot(1,1);solve(1,0);
cin>>Q;
while(Q--){
scanf("%d%d%d",&op,&x,&y);
if(op==2)printf("%d\n",query(id[x][y]));
else Modify(id[x][y]);
}
return 0;
}

Codeforces 936E. Iqea的更多相关文章

  1. python爬虫学习(5) —— 扒一下codeforces题面

    上一次我们拿学校的URP做了个小小的demo.... 其实我们还可以把每个学生的证件照爬下来做成一个证件照校花校草评比 另外也可以写一个物理实验自动选课... 但是出于多种原因,,还是绕开这些敏感话题 ...

  2. 【Codeforces 738D】Sea Battle(贪心)

    http://codeforces.com/contest/738/problem/D Galya is playing one-dimensional Sea Battle on a 1 × n g ...

  3. 【Codeforces 738C】Road to Cinema

    http://codeforces.com/contest/738/problem/C Vasya is currently at a car rental service, and he wants ...

  4. 【Codeforces 738A】Interview with Oleg

    http://codeforces.com/contest/738/problem/A Polycarp has interviewed Oleg and has written the interv ...

  5. CodeForces - 662A Gambling Nim

    http://codeforces.com/problemset/problem/662/A 题目大意: 给定n(n <= 500000)张卡片,每张卡片的两个面都写有数字,每个面都有0.5的概 ...

  6. CodeForces - 274B Zero Tree

    http://codeforces.com/problemset/problem/274/B 题目大意: 给定你一颗树,每个点上有权值. 现在你每次取出这颗树的一颗子树(即点集和边集均是原图的子集的连 ...

  7. CodeForces - 261B Maxim and Restaurant

    http://codeforces.com/problemset/problem/261/B 题目大意:给定n个数a1-an(n<=50,ai<=50),随机打乱后,记Si=a1+a2+a ...

  8. CodeForces - 696B Puzzles

    http://codeforces.com/problemset/problem/696/B 题目大意: 这是一颗有n个点的树,你从根开始游走,每当你第一次到达一个点时,把这个点的权记为(你已经到过不 ...

  9. CodeForces - 148D Bag of mice

    http://codeforces.com/problemset/problem/148/D 题目大意: 原来袋子里有w只白鼠和b只黑鼠 龙和王妃轮流从袋子里抓老鼠.谁先抓到白色老鼠谁就赢. 王妃每次 ...

随机推荐

  1. 实战iOS7之NSURLSession

    NSURLSession VS NSURLConnection NSURLSession可以看做是NSURLConnection的进化版,其对NSURLConnection的改进点有: * 根据每个S ...

  2. google chrome 调试技巧:监控 DOM 元素被修改

    在很多时候, 页面上一个元素的属于被修改.删除,子节点的添加与修改,很难一下找到对应的代码,在 google chrome 开发者工具里, 提供了对 DOM 元素的监控: 在 Elements 标签, ...

  3. JAVA篇之环境安装(Windows)

    一.JAVA 安装两个重要概念 1.JRE::英文Java Development Kit ,记住英文,深入理解就去看相关文章. 2.JDK:英文 Java Runtime Environment,记 ...

  4. spring boot 错误:Check your ViewResolver setup

    Whitelabel Error Page This application has no explicit mapping for /error, so you are seeing this as ...

  5. 图形学思考 - 聊聊透视图投射矩阵perspective projective matrix

    from:版权声明:本文作者靖心,靖空间地址:http://blog.csdn.net/kenden23/,未经本作者允许不得转载. 什么是透视图投射矩阵perspective projective ...

  6. P4597 序列sequence

    传送门 题解 完全看不懂大佬们在说什么……特别是chen_zhe大佬写的…… 来说说个人的理解吧 大佬们说:考虑当前的数$x$和之前的最大数$y$,(默认$x<y$,因为如果$x>=y$已 ...

  7. css中的左右垂直居中的问题,可兼容各种版本浏览器的写法

    如题分为垂直居中,左右居中,先挑简单的记录. 一.左右居中 1.我刚开始写代码的时候,老师就直接告诉我一个简单的方法,那就是: width:500px; height:200px; margin:0 ...

  8. noip提高组模拟赛(QBXT)T2

    T2count题解 [ 问题描述]: 小 A 是一名热衷于优化各种算法的 OIER,有一天他给了你一个随机生成的 1~n 的排列, 并定 义区间[l,r]的价值为: \[ \huge C_{l,r}= ...

  9. 51 Nod 1042 数位dp

    1042 数字0-9的数量 1 秒 131,072 KB 10 分 2 级题   给出一段区间a-b,统计这个区间内0-9出现的次数. 比如 10-19,1出现11次(10,11,12,13,14,1 ...

  10. CF1067D. Computer Game(斜率优化+倍增+矩阵乘法)

    题目链接 https://codeforces.com/contest/1067/problem/D 题解 首先,如果我们获得了一次升级机会,我们一定希望升级 \(b_i \times p_i\) 最 ...