首页 > 其他分享 >P3180 [HAOI2016] 地图

P3180 [HAOI2016] 地图

时间:2023-08-08 19:44:06浏览次数:39  
标签:10 P3180 bc int 地图 ++ HAOI2016 kmax low

Problem

给出 \(n\) 个点 \(m\) 条边的无向连通图,且每条边最多被包含在一个环中,每个点有颜色,有 \(q\) 次询问,每次询问给出一个点 \(x\) 和参数 \(y\),假如将 \(1\) 到 \(x\) 所有简单路径上的边删去后,从 \(x\) 出发,能到达的所有点中,颜色编号小于等于 \(y\) 且出现次数为奇数或偶数次的颜色有几种(没出现的颜色不统计)。

Input

一行两个整数 \(n,m\) 表示点数和边数

一行 \(n\) 个整数,表示每个点的颜色

\(m\) 行,每行两个整数 \(x,y\) 表示一条无向边

一行一个整数 \(q\),表示询问数

\(q\) 行,每行三个整数 \(opt,x,y\),\(opt=0\) 时询问偶数,\(opt=1\) 时询问奇数

Output

一共 \(q\) 行,对于每个询问输出一个答案。

Sample

Input 1

10 12
1 10 4 5 2 10 1 8 4 8
1 2
1 3
1 4
2 5
4 6
4 7
7 8
2 9
8 10
1 6
8 10
4 7
10
0 3 9
1 7 6
0 5 2
1 10 9
0 5 7
1 7 4
0 7 3
1 2 7
0 3 4
0 3 8

Output 1

0
1
0
1
0
1
0
2
0
0

Solution

不难发现一个性质,对原图建圆方树,那么删去 \(1\) 到 \(x\) 的所有简单路径后 \(x\) 所到达的点只有 \(x\) 的子树了。那么原问题就转化成一个经典的问题了,我们需要维护好子树内颜色出现的奇偶情况即可,可以考虑树上启发式合并套树状数组的方式求解。

代码:

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>

using namespace std;

const int kmax = 1e6 + 3;

struct E {
  int p, y;
} e[kmax << 1];

struct Q {
  int k, op, id;
};

int n, m, q;
int h[kmax], ec;
int ct;
int col[kmax];
int c[2][kmax];
vector<int> ee[kmax];
int dfn[kmax], low[kmax], idx;
int stk[kmax], tp;
int siz[kmax], son[kmax], num[kmax];
vector<Q> qry[kmax];
int bc[kmax];
int res[kmax];
int l[kmax], r[kmax];

void Addedge(int x, int y) {
  e[++ec] = {h[x], y};
  h[x] = ec;
}

void Tarjan(int x) { // 求点双
  dfn[x] = low[x] = ++idx;
  stk[++tp] = x;
  for (int i = h[x]; i; i = e[i].p) {
    int y = e[i].y;
    if (!dfn[y]) {
      Tarjan(y);
      low[x] = min(low[x], low[y]);
      if (dfn[x] == low[y]) {
        ct++;
        for (int z = 0; z != y; tp--) {
          z = stk[tp];
          ee[z].push_back(ct);
          ee[ct].push_back(z);
          //					cout << z << ' ' << ct << '\n';
        }
        ee[x].push_back(ct);
        ee[ct].push_back(x);
        //				cout << x << ' ' << ct << '\n';
      }
    } else {
      low[x] = min(low[x], dfn[y]);
    }
  }
}

int Lowbit(int x) {
  return x & -x;
}

void Modify(int x, int op, int v) {
  for (; x < kmax; x += Lowbit(x)) { // 树状数组修改
    c[op][x] += v;
  }
}

int Getres(int x, int op) {
  int tot = 0;
  for (; x; x -= Lowbit(x)) {
    tot += c[op][x];
  }
  return tot;
}

void Dfs(int x, int fa) {
  l[x] = ++idx;
  num[idx] = x;
  siz[x] = 1;
  for (int y : ee[x]) {
    if (y == fa) continue;
    Dfs(y, x);
    siz[x] += siz[y];
    if (siz[y] > siz[son[x]]) {
      son[x] = y;
    }
  }
  r[x] = idx;
}

void Change(int x, int v) {
  if (bc[x]) {
    Modify(x, bc[x] & 1, -1);
  }
  bc[x] += v;
  if (bc[x]) {
    Modify(x, bc[x] & 1, 1);
  }
}

void Dfss(int x, int fa) {
  for (int y : ee[x]) {
    if (y == fa || y == son[x]) continue;
    Dfss(y, x); // 先处理轻儿子
    for (int i = l[y]; i <= r[y]; i++) {
      Change(col[num[i]], -1);
    }
  }
  if (son[x]) Dfss(son[x], x); // 处理重儿子
  Change(col[x], 1); // 加入根节点
  for (int y : ee[x]) {
    if (y == fa || y == son[x]) continue;
    for (int i = l[y]; i <= r[y]; i++) {
      Change(col[num[i]], 1); // 将轻儿子的结果加入
    }
  }
  for (Q cur : qry[x]) {
    res[cur.id] = Getres(cur.k, cur.op); // 处理询问
  }
}

int main() {
  ios::sync_with_stdio(0);
  cin >> n >> m;
  for (int i = 1; i <= n; i++) {
    cin >> col[i];
    col[i]++;
  }
  for (int i = 1, x, y; i <= m; i++) {
    cin >> x >> y;
    Addedge(x, y);
    Addedge(y, x);
  }
  ct = n;
  for (int i = 1; i <= n; i++) {
    if (dfn[i]) continue;
    Tarjan(i); // 建圆方树
  }
  for (int i = n + 1; i <= ct; i++) {
    col[i] = kmax - 1; // 方点颜色设为极大值
  }
  //	cout << "ct = " << ct << '\n';
  cin >> q;
  for (int i = 1, op, x, k; i <= q; i++) {
    cin >> op >> x >> k;
    k++;
    qry[x].push_back({k, op, i});
  }
  idx = 0;
  Dfs(1, 0);
  //	for(int i = 1; i <= ct; i++) {
  //		cout << i << ' ' << l[i] << ' ' << r[i] << '\n';
  //	}
  Dfss(1, 0); // 树上启发式合并
  for (int i = 1; i <= q; i++) {
    cout << res[i] << '\n';
  }
  return 0;
}

标签:10,P3180,bc,int,地图,++,HAOI2016,kmax,low
From: https://www.cnblogs.com/ereoth/p/17615234.html

相关文章

  • 2023年8月最新全国省市区县和乡镇街道行政区划矢量边界坐标经纬度地图数据 shp geojso
    发现个可以免费下载全国 geojson 数据的网站,推荐一下。支持全国、省级、市级、区/县级、街道/乡镇级以及各级的联动数据,支持导入矢量地图渲染框架中使用,例如:D3、Echarts等geojson数据下载地址:https://geojson.hxkj.vip该项目github地址:https://github.com/TangSY/echarts-m......
  • TSINGSEE青犀视频安防监控EasyCVR视频汇聚平台电子地图定位偏移的排查与解决
    安防监控EasyCVR视频汇聚综合管理平台具有强大的数据接入、处理及分发能力,平台可提供视频监控直播、云端录像、云存储、录像检索与回看、告警上报与查询、平台级联、云台控制、语音对讲、电子地图、轨迹跟踪、H.265自动转码等视频能力。在视频监控管理平台TSINGSEE青犀视频EasyCVR......
  • [数据分析与可视化] Python绘制数据地图4-MovingPandas入门指北
    MovingPandas是一个基于Python和GeoPandas的开源地理时空数据处理库,用于处理移动物体的轨迹数据。它提供了一组强大的工具,可以轻松地加载、分析和可视化移动物体的轨迹。通过使用MovingPandas,用户可以轻松地处理和分析移动对象数据,并从中提取有关行为、模式和趋势的见解。无论是处......
  • 如何使用地图软件制作一个自定义的旅游线路示意图 All In One
    如何使用地图软件制作一个自定义的旅游线路示意图AllInOneVlog视频Vlog视频博客Videoblog、Videolog如何用GoogleMap制作旅游路线图创建新地图添加线路(自动生成连线)预览分享https://www.google.com/maps/d/https://www.google.com/maps/d/ed......
  • 开源视频监控管理平台国标GB28181视频EasyCVR电子地图功能展示优化
    视频汇聚平台EasyCVR可拓展性强、视频能力灵活、部署轻快,可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等,以及厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等。视频监控综合管理平台EasyCVR可提供的视频能力包括:视频监控直播、云端录像、云存储、录像检索与回......
  • java 地图生成瓦片的方法
    Java地图生成瓦片的方法作为一名经验丰富的开发者,我将指导你如何实现Java地图生成瓦片的方法。这个过程可以分为以下几个步骤:步骤描述步骤1获取地图数据步骤2将地图数据切割成瓦片步骤3保存瓦片到本地现在让我们一步步来实现这个过程。步骤1:获取地图数据......
  • (数据科学学习手札153)基于martin的高性能矢量切片地图服务构建
    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes1简介大家好我是费老师,在日常研发地图类应用的场景中,为了在地图上快速加载大量的矢量要素,且方便快捷的在前端处理矢量的样式,且矢量数据可以携带对应的若干属性字段,目前主流的做法......
  • 使用百度地图路书为骑行视频添加同步轨迹
    问题背景使用gopro记录骑行过程(参考《使用二手gopro做行车记录仪》),事后将视频文件导出来回顾整个旅程,会发现将它们与地图对应起来是一件困难的事。想要视频和地图对应,首先需要上报每个时刻的位置,gopro本身是支持的,然而要到版本5才可以,我的3+太老了没这能力。为此我......
  • 使用百度地图路书为骑行视频添加同步轨迹
    问题背景使用gopro记录骑行过程(参考《使用二手gopro做行车记录仪》),事后将视频文件导出来回顾整个旅程,会发现将它们与地图对应起来是一件困难的事。想要视频和地图对应,首先需要上报每个时刻的位置,gopro本身是支持的,然而要到版本5才可以,我的3+太老了没这能力。为此我......
  • (数据科学学习手札153)基于martin的高性能矢量切片地图服务构建
    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes1简介大家好我是费老师,在日常研发地图类应用的场景中,为了在地图上快速加载大量的矢量要素,且方便快捷的在前端处理矢量的样式,且矢量数据可以携带对应的若干属性字段,目前主流的做法......