首页 > 编程语言 >莫队算法学习笔记

莫队算法学习笔记

时间:2023-09-09 11:33:25浏览次数:45  
标签:cnt bel int tp 算法 maxn 笔记 莫队 define

莫队

  • 普通莫队

    • 这个很基础。
  • 带修莫队

  • 就在普通莫队的基础上加上时间这一维度。

  • [P1903 国家集训队] 数颜色 / 维护队列

  • 回滚莫队

    • 为什么要回滚? 因为有些信息不好撤销,比如区间众数。

    • 和普通莫队相比较,就是对于每一个块,左端点放在块的右端点处,每次向左扩展,临时记录答案,

    • 对于右端点,由于我们排序时是将一个块内的右端点从小到大排序,所以按照普通莫队的扩展就行。

    • 块间的转换直接全部清空。

    • 【模板】回滚莫队&不删除莫队

    • JOISC 2014 Day1 历史研究

  • 树上莫队

    • 首先我们得会树上分块

    • 有按大小(size),深度(dep)不同的分块方式, 取决于题目。

    • 按 size 分块的思想可以参考 [P2325 SCOI2005] 王室联邦

    • 简单来讲,就是优先填下面的,满了阈值就更新, 随后上面剩下的和根一组。

    • 拿这题举例[P4074 WC2013] 糖果公园

    • 树分块之后, 我们类似在树上游走做修改莫队,注意lca处可能会出现问题,所以我们每次临时将lca点上,最后再撤销。

  • 附录(树size分块代码)

    int st[maxn], tp;
    int bel[maxn];
    vector<int> G[maxn];
    int pro[maxn];
    int B, cnt;
    void dfs(int x, int f) {
    	int cur = tp;
    	for (auto i : G[x]) {
    		if (i != f) {
    			dfs(i, x);
    			if (tp - B >= cur) {
    				cnt++;
    				pro[cnt] = x;
    				while(tp > cur) {
    					bel[st[tp--]] = cnt;
    				}
    			}
    		}
    	}
    	st[++tp] = x;
    }
    // main
    	if (!cnt) cnt++;
    	while(tp) {
    		bel[st[tp--]] = cnt;
    	}
    	pro[cnt] = 1;
    
  • [P4074 [WC2013] 糖果公园] 代码

#include <bits/stdc++.h>
#define for_(i,a,b) for (int i = (a); i < (b); i++)
#define rep_(i,a,b) for (int i = (a); i <= (b); i++)
#define per_(i,a,b) for (int i = (a); i >= (b); i--)
#define pii pair<int, int>
#define pll pair<ll, ll> 
#define fi first
#define se second
#define ll long long
#define sz(a) (int)a.size()
#define all(v) v.begin(), v.end()
#define clr(x) memset(x, 0, sizeof(x))
#define wls(v)   sort(all(v)); v.erase(unique(all(v)), v.end());
#define ull unsigned long long
#define pb push_back
#define D(x) cerr << #x << '=' << x << endl
#define outarr(a,L,R) cerr<<#a"["<<L<<".."<<R<<"]=";rep_(_x,(L),(R))cerr<<a[_x]<<" "; cerr<<endl; 
	#ifdef LOCAL
#define line cout << "--------------------------------" << endl;
#define CE cout << endl;
#define CO cout << "OK" << endl;
    #endif
#define endl '\n'
#define int ll
using namespace std;
bool be;clock_t startTime;
double getCurrentTime() {
	return (double)(clock() - startTime) / CLOCKS_PER_SEC;
}
const int maxn = 2e5 + 10, mod = 998244353;// mod = 1949777;
const double EPS = 1e-3;
template <typename Type>
void add(Type &x, Type y, Type Md = mod) {
	x += y; while(x >= Md) x -= Md;
	while(x < 0) x += Md;
}
int n, m;
int a[maxn], v[maxn], w[maxn], ra[maxn];
bool ed;
void solve() {
}
int B = 2000;
struct node{
	int l, r, t;
	int id;
}b[maxn];
struct Cnode{
	int x, y, prx, t;
}c[maxn];
int q;
// ----------------------------------
vector<int> G[maxn];
int fa[maxn], son[maxn], sz[maxn], dep[maxn];
int st[maxn], top, bel[maxn], cnt;
void dfs1(int x, int f) {
	sz[x] = 1, fa[x] = f, dep[x] = dep[f] + 1;
	int cur = top;
	for(auto i : G[x]) {
		if (i != f) {
			dfs1(i, x);
			sz[x] += sz[i];
			if (sz[i] > sz[son[x]]) son[x] = i;
			if (top - cur >= B) {
				cnt++;
				while(top > cur) {
					bel[st[top--]] = cnt;
				}
			}
		}
	}
	st[++top] = x;
	return;
}
int tp[maxn];
void dfs2(int x, int fp) {
	tp[x] = fp;
	if (son[x]) {
		dfs2(son[x], fp);
	}
	for (auto i : G[x]) {
		if (!tp[i]) assert(i != fa[x] && i != son[x]);
		if (i != fa[x] && i != son[x]) {
			dfs2(i, i);
		}
	}
}
int lca(int x, int y) {
	while(tp[x] != tp[y]) {
		if (dep[tp[x]] < dep[tp[y]]) swap(x, y);
		x = fa[tp[x]]; 
	}
	if (dep[x] > dep[y]) return y;
	else return x;
}
bool cmp(node &x, node &y) {
	if (bel[x.l] != bel[y.l]) return bel[x.l] < bel[y.l];
	else if (bel[x.r] != bel[y.r]) return bel[x.r] < bel[y.r];
	else return x.t < y.t;
}
//------------------------------
int vis[maxn];
int occurence[maxn];
int ans = 0, Ans[maxn];
void upd(int x) {
	if (vis[x]) {
		ans -= w[occurence[a[x]]] * v[a[x]]; 
		occurence[a[x]]--;
	} else {
		occurence[a[x]]++;
		ans += w[occurence[a[x]]] * v[a[x]]; 
	}
	vis[x] ^= 1;
}
void move(int x, int y) {
	if (dep[x] < dep[y]) swap(x, y);
	while(dep[x] != dep[y]) upd(x), x = fa[x];
	while(x != y) upd(x), x = fa[x], upd(y), y = fa[y];
	return; 
}
void chg(int x, int y) {
	int flag = vis[x];
	if (flag) upd(x);
	a[x] = y;
	if (flag) upd(x);
}
signed main() {
	#ifdef LOCAL
		freopen("w.in", "r", stdin);
//		freopen("w.out", "w", stdout);
		startTime = clock();
		time_t now_time = time(NULL); tm* TuT = localtime(&now_time); cout << asctime(TuT); cout << "CodeBegin:_______________________" << endl;
		cerr << "Memory footprint:" << ((&be - &ed) >> 20) <<"MB"<< endl;
		line;
	#endif
//	freopen("park.in", "r", stdin);
//	freopen("park.out", "w", stdout);
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
//  int tt; cin >> tt; while(tt--) solve();	
	cin >> n >> m >> q; 
	rep_(i, 1, m) {
		cin >> v[i];
	}
	rep_(i, 1, n) {
		cin >> w[i];
	}
	rep_(i, 1, n - 1) {
		int u, v; cin >> u >> v; G[u].pb(v); G[v].pb(u);
	}
	
	dfs1(1, 0);
	if (!cnt) cnt++;
	while(top) {
		bel[st[top--]] = cnt;
	}
	dfs2(1, 1);
	rep_(i, 1, n) {
		cin >> a[i];
		ra[i] = a[i];
	}
	int now_t = 0, opt, x, y;
	int nq = 0;
	rep_(i, 1, q) {
		cin >> opt >> x >> y;
		if(opt == 0) {
			now_t++;
			c[now_t].x = x;
			c[now_t].y = y;
			c[now_t].prx = ra[x];
			ra[x] = y;
		} else {
			nq++;
			b[nq].t = now_t;
			b[nq].l = x, b[nq].r = y;
			b[nq].id = nq;
		}
	}
	memcpy(ra, a, sizeof(a));

	q = nq;
	sort(b + 1, b + q + 1, cmp);
	int l = 1, r = 1, t = 0;
	rep_(i, 1, nq) {
		if (l != b[i].l) move(l, b[i].l), l = b[i].l;
		if (r != b[i].r) move(r, b[i].r), r = b[i].r;
		int f = lca(l, r);
		upd(f);
		while(t < b[i].t) {
			t++;
			chg(c[t].x, c[t].y);
		}
		while(t > b[i].t) {
			chg(c[t].x, c[t].prx);
			t--;
		}
		Ans[b[i].id] = ans;
		upd(f);
	} 
	rep_(i, 1, nq) {
		cout << Ans[i] << '\n'; 
	}
  	#ifdef LOCAL
  	cerr<<"\n\n-----------------------\nProgram done in "<<clock()-startTime<<" ms";
	#endif
 	return 0; 
}
//by whc
// check if over int , and open long long !!!
// check if it will RE !!! Is it only 2e5+10?? Maynot!
 
 

标签:cnt,bel,int,tp,算法,maxn,笔记,莫队,define
From: https://www.cnblogs.com/Cranew/p/17689110.html

相关文章

  • 学习笔记1 代码
    学习所用代码test.c#include<stdio.h>intmain(){printf("hello");return0;}hello.h#ifndef_HELLO_H#define_HELLO_H/***fuction:printhellostring.*parm:void*returnvalue:void*/voidsay_hello()......
  • 代码随想录算法训练营第三天| 203.移除链表元素 707.设计链表 206.反转链表
    203.移除链表元素链表定义structListNode{intval;ListNode*next;ListNode():val(0),next(NULL){};ListNode(intx):val(x),next(NULL){};ListNode(intx,ListNode*next):val(x),next(next){};}1.在原链表上移除链表元素classSolut......
  • 铺地毯---算法题
    题目描述为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯。一共有张地毯,编号从到。现在将这些地毯按照编号从小到大的顺序平行于坐标轴先后铺设,后铺的地毯覆盖在前面已经铺好的地毯之上。地毯铺设完成后,组织者想知道......
  • 红日ATT&CK系列靶场(五)笔记
    环境搭建第一次登录会提示需要更改账号密码。win7账号密码:sun\heart123.comsun\Administratordc123.com—————————————————————————————————————————————————————————————2008账号密码sun\admin20......
  • 新人笔记-继承简略
    packagecom_black.jicheng;//调试类publicclassDemo{publicstaticvoidmain(String[]args){//创建对象调用方法fuc=newfu();c.show();ziz=newzi();z.method();z.show();}}packagecom_black......
  • 基于分水岭算法的图像分割-Matlab版本
    ✅作者简介:热爱科研的算法开发者,Python、Matlab项目可交流、沟通、学习。......
  • 基于Fast-RCNN深度学习网络的交通标志检测算法matlab仿真
    1.算法理论概述      Fast-RCNN是一种基于深度学习的目标检测算法,可以用于检测图像中的目标物体。交通标志检测是交通场景下的一项重要任务,它可以在道路上的交通标志被遮挡或损坏时提供帮助。基于Fast-RCNN深度学习网络的交通标志检测算法可以对交通场景下的图像进行检测,......
  • 算法通关村第一关——链表青铜挑战笔记
    算法通关村第一关——链表青铜挑战笔记链表是一种经典的数据结构,在很多软件里大量使用,例如操作系统、JVM等。在面试中链表题目数量少,类型也相对固定,考察频率却非常高,因此我们只要将常见题目都学完就万事大吉了,所以链表特别值得刷。单链表的概念链表的概念单向链表就像一个......
  • c语言学习之路--static的用法(笔记)
    1.static修饰局部变量时可以理解为将局部变量变为全局变量,如图:#include<stdio.h>voidtest(void){ inta=1; a++; printf("a的值为%d\n",a); }intmain(void){ inti=0; while(i<5){ i++; test(); } return0;}没有static时结果为a的值为2a的值为2......
  • 学习笔记1
    目录知识点归纳苏格拉底挑战问题与解决思路实践过程先让chatgpt给我点linux命令,我来实践知识点归纳苏格拉底挑战问题与解决思路我下载了虚拟机,并装好了镜像文件,但是对于linux命令行的环境尚未配置,我咨询chatgpt给我回答实践过程先让chatgpt给我点linux命令,我来实践......