首页 > 其他分享 >【学习笔记】线段树分治

【学习笔记】线段树分治

时间:2023-08-09 22:45:43浏览次数:46  
标签:sz ch sta int 线段 分治 tot 笔记

定义

线段树分治是一种解决一类有插入、删除和整体查询操作的问题的方法。它是一种离线做法,通过在线段树上记录操作的时间区间来处理修改对询问的影响。每个操作被看作一个时间区间的修改,并在线段树上进行标记。然后通过深度优先搜索(DFS)依次执行这些操作,直到根节点来回答查询,并在离开时将其撤销。


 题目

#121. 「离线可过」动态图连通性

  1 #include <bits/stdc++.h>
  2 #define fo(a,b,c) for(int a=b;a<=c;a++)
  3 #define re(a,b,c) for(int a=b;a>=c;a--)
  4 #define mod 1000000007
  5 #define inp 10000019
  6 using namespace std;
  7 const int N = 500005;
  8 
  9 inline int read() {
 10     int x = 0, f = 1;
 11     char ch = getchar();
 12 
 13     while (ch < '0' || ch > '9') {
 14         if (ch == '-')
 15             f = -1;
 16 
 17         ch = getchar();
 18     }
 19 
 20     while (ch >= '0' && ch <= '9') {
 21         x = (x << 1) + (x << 3) + (ch ^ 48);
 22         ch = getchar();
 23     }
 24 
 25     return x * f;
 26 }
 27 
 28 int nyn = 1;
 29 int n, e[5005][5005], cnt, st[N], en[N], fr[N], to[N], f[N];
 30 int op2l[N], op2r[N], sz[N], tot;
 31 
 32 struct sss {
 33     int x, y, szx, szy;
 34 } sta[N];
 35 
 36 int find(int x) {
 37     if (f[x] == x)
 38         return x;
 39 
 40     return find(f[x]);
 41 }
 42 
 43 void merge(int x, int y) {
 44     x = find(x);
 45     y = find(y);
 46 
 47     if (x == y)
 48         return;
 49 
 50     tot++;
 51 
 52     if (sz[x] > sz[y])
 53         swap(x, y);
 54 
 55     sta[tot].x = x;
 56     sta[tot].y = y;
 57     sta[tot].szx = sz[x];
 58     sta[tot].szy = sz[y];
 59     f[x] = y;
 60     sz[y] += sz[x];
 61 }
 62 
 63 void split(int k) {
 64     while (tot > k) {
 65         int x = sta[tot].x, y = sta[tot].y;
 66         int szx = sta[tot].szx;
 67         int szy = sta[tot].szy;
 68         f[x] = x;
 69         sz[x] = szx;
 70         sz[y] = szy;
 71         tot--;
 72     }
 73 }
 74 
 75 struct IO {
 76     vector<int> t;
 77 } node[N * 4];
 78 
 79 void ud(int rt, int l, int r, int L, int R, int val) {
 80     if (l > r)
 81         return;
 82 
 83     if (L <= l && r <= R) {
 84         node[rt].t.push_back(val);
 85         return;
 86     }
 87 
 88     int mid = (l + r) / 2;
 89 
 90     if (L <= mid)
 91         ud(rt * 2, l, mid, L, R, val);
 92 
 93     if (R >= mid + 1)
 94         ud(rt * 2 + 1, mid + 1, r, L, R, val);
 95 }
 96 
 97 void qr(int rt, int l, int r) {
 98     int num = tot;
 99 
100     for (int i = 0; i < node[rt].t.size(); i++) {
101         int x = node[rt].t[i];
102         merge(fr[x], to[x]);
103     }
104 
105     if (l == r) {
106         if (l == 1)
107             return;
108 
109         int x = op2l[l], y = op2r[l];
110         int fx = find(x), fy = find(y);
111 
112         if (fx == fy)cout << "Y\n";
113         else cout << "N\n";
114 
115         split(num);
116         return;
117     }
118 
119     int mid = (l + r) / 2;
120     qr(rt * 2, l, mid);
121     qr(rt * 2 + 1, mid + 1, r);
122     split(num);
123 }
124 
125 int dp[N];
126 void sol() {
127     n = read();
128 
129     for (int i = 1; i <= n; i++)
130         f[i] = i, sz[i] = 1;
131 
132     int m = read();
133     int tm = 1;
134 
135     for (int i = 1; i <= m; i++) {
136         int op = read();
137 
138         if (op == 0) {
139             cnt++;
140             int x = read();
141             int y = read();
142             fr[cnt] = x;
143             to[cnt] = y;
144             e[x][y] = e[y][x] = cnt;
145             st[cnt] = tm + 1;
146         } else if (op == 1) {
147             int x = read();
148             int y = read();
149             en[e[x][y]] = tm;
150             e[x][y] = 0;
151         } else {
152             tm++;
153             op2l[tm] = read();
154             op2r[tm] = read();
155         }
156     }
157 
158     for (int i = 1; i <= cnt; i++)
159         if (en[i])
160             ud(1, 1, tm, st[i], en[i], i);
161         else
162             ud(1, 1, tm, st[i], tm, i);
163 
164     qr(1, 1, tm);
165 }
166 
167 int main() {
168     while (nyn--) {
169         sol();
170         printf("\n");
171     }
172 }

P5787 二分图 /【模板】线段树分治

线段树分治

嘻嘻,结束!

标签:sz,ch,sta,int,线段,分治,tot,笔记
From: https://www.cnblogs.com/life-like-VEX/p/17618196.html

相关文章

  • 做题笔记
    [AT_abc313_d]OddorEven简单题,但是为什么赛场上WA了呢?弱化题目,设\(n=k+1\),发现只需要每一个数不取询问\(k\)次,通过前缀和得出。再设\(k+1\|\n\),发现只需要类似分块即可解决。回到原题,最后的一部分如何计算?我们可以对\([n-k,n]\)这个区间做询问,但是对......
  • openGauss学习笔记-35 openGauss 高级数据管理-ALTER TABLE语句
    openGauss学习笔记-35openGauss高级数据管理-ALTERTABLE语句修改表,包括修改表的定义、重命名表、重命名表中指定的列、重命名表的约束、设置表的所属模式、添加/更新多个列、打开/关闭行访问控制开关。35.1语法格式在一张已经存在的表上添加列。ALTERTABLEtable_name......
  • 线段树的一些延伸
    一.动态开点线段树简介虽然思路简单,但对于一个习惯数组写法的人,这是一个比较难受的东西。动态开点一般是用来解决空间上的问题的。一般来说,普通的线段树是直接将一颗完整的线段建出来,但如碰到数据范围大或卡空间的时候,我们就只能在我们需要的时候再建,这个就叫做动态开点。(类似......
  • [刷题笔记] Luogu P1280 尼克的任务
    ProblemAnalysis首先,如果一个时间只有一个任务开始,则她必须做。如果一个时间有多个任务开始,她可以选一个去做。我们发现这样的决策是取决于后面的空暇时间,而不是前面。所以在dp的时候需要从后往前搜时间(当然如果从前往后可以跑记搜)考虑转移,如果一个时间有多个任务开始,则选一个......
  • 【转录】卡片笔记法:从卢曼卡片盒到ANTINET
    在我们探讨卢曼卡片盒的使用成本时,我们发现真正的成本不仅在于时间投入,更在于个体面临的认知挑战。而当我们探讨ANTINET与双链笔记法的对比时,我们看到了信息组织方式的转变,从相对混沌的状态走向更加秩序化的分叉结构。然而,这种转变不仅限于信息的组织,更包括了我们笔记工具的选择:......
  • ABC245E Wrapping Chocolate [线段树二分]
    也许更好的阅读体验\(\mathcal{Description}\)\(n\)个物品有长和宽,\(m\)个盒子也有长和宽,一个盒子最多可以装一个物品,问\(n\)个物品能否都放进盒子,物品和盒子不能旋转\(\mathcal{Solution}\)先离散化长和宽,将物品和盒子按照长从大到小排序考虑到当前物品时将所有长大于等于当......
  • MySQL数据库笔记(一)
    第一章数据库概述1、什么是数据库数据库是一种存储并管理数据的软件系统存储:持久化管理:增删改查常用的存储数据的方式:1、Java中的变量:生命周期短,不能实现持久化[内存]2、序列化:管理数据时依赖于Java中的反序列化[硬盘]3、txt,办公软件:没有统一的方式管理数据[硬盘]4......
  • 主成分分析(PCA)模型学习笔记(一)
    目录为什么使用PCA从过拟合说起维度灾难模型定义PCA的两种推导数据准备最大投影方差最小重构距离小结为什么使用PCA从过拟合说起在数据量小、数据维度高,模型较为复杂时,很容易产生过拟合。训练误差小而泛化误差较大被称为过拟合,而我们所追求的是泛化误差较小,为了解决过拟合问题,......
  • 线性判别分析(LDA)模型笔记
    目录模型概况模型定义模型求解模型概况线性判别方法(LinearDiscriminationAnalysis)是一种经典的线性学些方法,最早由Fisher提出,也叫“Fisher判别分析”。LDA的思想非常朴素,也即是,将样例投影到一条直线上使得同类样例的投影点尽可能近,异类样例的投影点尽可能远,总结六个字就是......
  • avue-crud属性配置项参数笔记分享
     Avue是一个基于Element-plus低代码前端框架,它使用JSON配置来生成页面,可以减少页面开发工作量,极大提升效率;虽然Avue官网上面都有这些配置说明,但是如果刚开始接触不熟悉框架的话需要很久才找到自己需要的参数配置,为了方便自己今后查找使用,现将一些开发中常用的配置梳理在下......