【题目描述】

Hoshizora Rin是个特别好动的少女。

一天Rin来到了一个遥远的都市。这个都市有N个建筑,编号从1到N,其中市中心编号为1,这个都市有M条双向通行的街道,每条街道连接着两个建筑,其中某些街道首尾相连连接成了一个环。Rin通过长时间的走访,已经清楚了这个都市的两个特点:

  1. 从市中心出发可以到达所有的建筑物。
  2. 任意一条街道最多存在与一个简单环中。

令Rin心花怒放的是,每个建筑物都会有拉面售卖。拉面有很多不同的种类,但对于Rin而言只有油腻程度的不同,因此我们把油腻程度相同的拉面看做同一种拉面。由于不同建筑物的拉面的油腻程度可能不同,我们用一个正整数来表示拉面的油腻程度。

要知道,拉面可是Rin的最爱,但是现在到了下班高峰期,都市的交通变得非常的堵塞。Rin只能通过没有被堵死的街道通行,去品尝所在建筑物的拉面。

现在Rin想知道,如果她正在编号为x的建筑物,那么在从市中心到x的所有简单路径经过的街道都被堵死的情况下,Rin可以品尝到的拉面中(注意没有出现的拉面是不能算在里面的):

  1. 油腻程度≤y且品尝次数为奇数次的拉面有多少种?
  2. 油腻程度≤y且品尝次数为偶数次的拉面有多少种?

【输入格式】

第一行两个正整数N,M,含义如题所示。

第二行一共N个正整数,第i个数Ai表示第i个建筑物出售的拉面的油腻程度。

接下来M行,每行两个正整数x,y,表示在建筑物x,y之间有一条双向通行的街道。数据保证1≤x<y≤N。

接下来一行一个正整数Q,表示询问个数。

接下来Q行每行三个非负整数ty,x,y,x表示询问的建筑物编号,y表示油腻程度的限制,ty=0时表示询问偶数,ty=1表示询问奇数。

【输出格式】

一共Q行,对于每个询问输出一个答案。

【样例输入】

5 6
2 1 6 7 7
1 2
1 3
2 4
4 5
4 5
1 3
3
0 3 2
0 3 1
0 1 7

【样例输出】

0
0
1

【样例解释】

3号建筑物只能到达它自己,而1号建筑物可以到达所有建筑物。

【数据范围】

提示:请注意数据范围中的≤,特殊条件中提到的y均为询问中的y,对于100%的数据,有y≤106。

对仙人掌进行了一遍dfs,得到dfs树

对于每个环,dfs序最小的叫做环的环根

在1到x的简单路径都不能走的限制下,从点x出发,能走到的点记为x的子树

如果x在环上 且 x不是环根,那么x的子树为 dfs序大于x的dfs序 且 不和x在同一个环上的点

如果x在环上 且 x是环根,那么所有dfs序大于x的dfs序的 点 都是x的子树

也就是说,环上点的子树只能累积到环根那里

定义 x的子树大小为son[x],x的dfs序为id[x]

那么对于每一个询问,就是查询 区间[id[x],id[x]+son[x]-1] 内有多少个点的油腻度<=y

用莫队

cnt[k] 表示 油腻度为k的点的个数

对油腻度 也分块 统计

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 100001
#define M 150001
using namespace std;
int n,m;
int o[N],oil[N];
int tot,front[N],nxt[M<<],to[M<<];
int dfn[N],low[N],dy[N];
int id[N],son[N];
int siz1,siz2;
int ans[N],tmp,sum[][N],cnt[N*],bl[N];
bool ins[N];
struct node
{
int l,r,ty,lim,num;
}e[N];
void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
}
void add(int u,int v)
{
to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
to[++tot]=u; nxt[tot]=front[v]; front[v]=tot;
}
void tarjan(int now,int last)
{
dfn[now]=low[now]=++tot;
dy[tot]=now;
for(int i=front[now];i;i=nxt[i])
{
if(to[i]==last) continue;
if(!dfn[to[i]])
{
tarjan(to[i],now);
low[now]=min(low[now],low[to[i]]);
}
else low[now]=min(low[now],dfn[to[i]]);
}
}
void dfs(int now)
{
ins[now]=true;
id[now]=++tot;
son[now]++;
for(int i=front[now];i;i=nxt[i])
if(!ins[to[i]])
if(low[to[i]]>=dfn[now])
{
dfs(to[i]);
son[now]+=son[to[i]];
}
for(int i=front[now];i;i=nxt[i])
if(!ins[to[i]])
{
dfs(to[i]);
son[dy[low[to[i]]]]+=son[to[i]];
}
}
bool cmp(node p,node q)
{
if(bl[p.l]!=bl[q.l]) return bl[p.l]<bl[q.l];
return p.r<q.r;
}
void up(int pos,bool ty)
{
int p=(oil[pos]-)/siz2+;
if(ty)
{
if(cnt[oil[pos]]&) --sum[][p],++sum[][p];
else if(cnt[oil[pos]]) --sum[][p],++sum[][p];
else ++sum[][p];
++cnt[oil[pos]];
}
else
{
if(cnt[oil[pos]]==) --sum[][p];
else if(cnt[oil[pos]]&) --sum[][p],++sum[][p];
else --sum[][p],++sum[][p];
--cnt[oil[pos]];
}
}
bool cal(int x,bool ty)
{
tmp=;
int last=(x-)/siz2+;
for(int i=;i<last;i++) tmp+=sum[ty][i];
for(int i=(last-)*siz2+;i<=x;i++)
if(cnt[i] && (cnt[i]&)==ty) tmp++;
}
int main()
{
//freopen("map_2016.in","r",stdin);
//freopen("map_2016.out","w",stdout);
read(n); read(m);
siz1=sqrt(n);
for(int i=;i<=n;i++) bl[i]=(i-)/siz1+;
int maxn=;
for(int i=;i<=n;i++) read(o[i]),maxn=max(maxn,o[i]);
siz2=sqrt(maxn);
int u,v;
for(int i=;i<=m;i++) read(u),read(v),add(u,v);
tot=;
tarjan(,);
tot=;
dfs();
for(int i=;i<=n;i++) oil[id[i]]=o[i];
int q,x;
read(q);
for(int i=;i<=q;i++)
{
read(e[i].ty);
read(x);
e[i].l=id[x];
e[i].r=id[x]+son[x]-;
read(e[i].lim);
e[i].num=i;
}
sort(e+,e+q+,cmp);
int L=,R=;
for(int i=;i<=q;++i)
{
while(R<e[i].r) up(++R,true);
while(L>e[i].l) up(--L,true);
while(R>e[i].r) up(R--,false);
while(L<e[i].l) up(L++,false);
cal(e[i].lim,e[i].ty);
ans[e[i].num]=tmp;
}
for(int i=;i<=q;i++) printf("%d\n",ans[i]);
}

HNOI 2016 地图的更多相关文章

  1. [HNOI 2016]树

    Description 题库链接 给你一棵 \(N\) 个节点根节点为 \(1\) 的有根树,结点的编号为 \(1\sim N\) :我们称这颗树为模板树.需要通过这棵模板树来构建一颗大树.构建过程如 ...

  2. 【BZOJ 4539】【HNOI 2016】树

    http://www.lydsy.com/JudgeOnline/problem.php?id=4539 今天测试唯一会做的一道题. 按题目要求,如果暴力的把模板树往大树上仍,最后得到的大树是$O(n ...

  3. hnoi 2016 省选总结

    感觉省选好难的说...反正我数据结构太垃圾正解想到了也打不出来打一打暴力就滚粗了! DAY1 0+20+30 DAY2 60-20+0+60 最后170-20分,暴力分还是没有拿全! 然而这次是给了5 ...

  4. HNOI 2016 省队集训日记

    第一天 DeepDarkFantasy 从东京出发,不久便到一处驿站,写道:日暮里.  ——鲁迅<藤野先生> 定义一个置换的平方为对1~n的序列做两次该置换得到的序列.已知一个置换的平方, ...

  5. 数据结构(树链剖分,堆):HNOI 2016 network

    2215. [HNOI2016]网络 ★★★☆   输入文件:network_tenderRun.in   输出文件:network_tenderRun.out   简单对比时间限制:2 s   内存 ...

  6. [HNOI 2016]最小公倍数

    Description 题库链接 给定一张 \(N\) 个顶点 \(M\) 条边的无向图(顶点编号为 \(1,2,\cdots,n\) ),每条边上带有权值.所有权值都可以分解成 \(2^a\time ...

  7. [HNOI 2016]序列

    Description 题库链接 给你一个长度为 \(n\) 的序列 \(A\) ,给出 \(q\) 组询问.每次询问 \([l,r]\) ,求该区间内所有的子序列中最小值的和. \(1\leq n, ...

  8. [HNOI 2016]大数

    Description 题库链接 给你一个长度为 \(n\) ,可含前导零的大数,以及一个质数 \(p\) . \(m\) 次询问,每次询问你一个大数的子区间 \([l,r]\) ,求出子区间中有多少 ...

  9. [HNOI 2016]网络

    Description 一个简单的网络系统可以被描述成一棵无根树.每个节点为一个服务器.连接服务器与服务器的数据线则看做 一条树边.两个服务器进行数据的交互时,数据会经过连接这两个服务器的路径上的所有 ...

随机推荐

  1. php面试全套

    7.mvc是什么?相互间有什么关系? 答:mvc是一种开发模式,主要分为三部分:m(model),也就是模型,负责数据的操作;v(view),也就是视图,负责前后台的显示;c(controller), ...

  2. 一:yarn 介绍

        yarn的了出现主要是为了拆分jobtracker的两个核心功能:资源管理和任务监控,分别对应resouceManager(RM)和applicationManager(AM).yarn中的任 ...

  3. js经典试题之ES6

    js经典试题之ES6 1:在ECMAScript6 中,Promise的状态 答案:pending  resolved(fulfilled) rejected 解析: Promise对象只有三种状态: ...

  4. Git 命令详解及常用命令

    Git 命令详解及常用命令 Git作为常用的版本控制工具,多了解一些命令,将能省去很多时间,下面这张图是比较好的一张,贴出了看一下: 关于git,首先需要了解几个名词,如下: 1 2 3 4 Work ...

  5. lintcode-151-买卖股票的最佳时机 III

    151-买卖股票的最佳时机 III 假设你有一个数组,它的第i个元素是一支给定的股票在第i天的价格.设计一个算法来找到最大的利润.你最多可以完成两笔交易. 注意事项 你不可以同时参与多笔交易(你必须在 ...

  6. 数据库集群之路二 MYCAT

    windows下安装配置并使用mycat 参考:http://www.cnblogs.com/parryyang/p/5758087.html 一 下载windows版本 https://github ...

  7. SpringData——HelloWorld

    1.背景 最开始了解SpringData的时候,以为他不就是ORM的一种实现方式嘛,还能有什么新的东西.从hibernate到ibatis.mybatis,也许他只不过是spring想整合一个更方便的 ...

  8. python爬虫从入门到放弃(五)之 正则的基本使用(转)

    什么是正则表达式 正则表达式是对字符串操作的一种逻辑公式,就是 事先定义好的一些特定字符.及这些特定字符的组合,组成一个“规则字符”,这个“规则字符” 来表达对字符的一种过滤逻辑. 正则并不是pyth ...

  9. 什么是Oracle的分区表 (转 作者 陈字文)

    假设我们现在正在酝酿经营一家图书馆,最初,我们只有十本书提供给大家来阅读和购买.对于十本书而言,我们可能只需要一个书架格子将其作为保存这十本书的容器就足够了,因为任何一个人都可以很轻松的扫一眼就可以将 ...

  10. 关于new delete的说明

    1. 删除空指针不会有问题,因为C++的标准规定在delete时首先会判断指针是否为空,为空就不再处理,所以也就不会有问题. 2. delete一个非空指针之后,并不会将该指针自动置为空.此时如果重复 ...