pyyzDay13

杂题选讲

T1 数颜色

vector存颜色

二分查找

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<bits/stdc++.h>
#define int long long
#define jiaa(a,b) {a+=b;if(a>=MOD) a-=MOD;}
#define jian(a,b) {a-=b;if(a<0) a+=MOD;}
using namespace std;
int ksm(int a,int b,int p){
	if(b==0) return 1;
	if(b==1) return a%p;
	int c=ksm(a,b/2,p);
	c=c*c%p;
	if(b%2==1) c=c*a%p;
	return c%p;	
}
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
vector<int> col[300005];
int ccc[300005];
signed main()
{
	//freopen("filename.in", "r", stdin);
	//freopen("filename.out", "w", stdout);
	int n=read(),m=read();
	for(int i=1;i<=n;i++){
		ccc[i]=read();
		col[ccc[i]].push_back(i);
	}
	while(m--){
		int opt=read();
		if(opt==1){
			int l=read(),r=read(),c=read();
			int pl=lower_bound(col[c].begin(),col[c].end(),l)-col[c].begin()-1;
			int pr=upper_bound(col[c].begin(),col[c].end(),r)-col[c].begin()-1;
			if(pr-pl<=0) cout<<0<<'\n';
			else cout<<pr-pl<<'\n';
		}
		else{
			int x=read();
			int co1=ccc[x];
			int co2=ccc[x+1];
			if(co1==co2) continue;
			int pp=lower_bound(col[co1].begin(),col[co1].end(),x)-col[co1].begin();
			col[co1][pp]=x+1;
			pp=lower_bound(col[co2].begin(),col[co2].end(),x+1)-col[co2].begin();
			col[co2][pp]=x;
			swap(ccc[x],ccc[x+1]);
		}
	}
	return 0;
}

T2 [JXOI2017] 加法

二分答案

区间左端点排序

每次选包含i的区间的右端点最大的

堆维护

树状数组维护差分

T3 [USACO20JAN] Cave Paintings P

dp+并查集维护连通块

T4 [ARC016D] 軍艦ゲーム

期望DP

发现母港形成环

二分答案破环成链

得到真答案与二分答案比较

trick:在DP中遇到环,且环的原因是某个值,可以直接二分这个值,得到真答案作比较

T5 koishi的数学题

数论分块

也可递推

调和级数求因数和

线性做法考虑线性求因数和

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<bits/stdc++.h>
#define int long long
#define jiaa(a,b) {a+=b;if(a>=MOD) a-=MOD;}
#define jian(a,b) {a-=b;if(a<0) a+=MOD;}
using namespace std;
int ksm(int a,int b,int p){
	if(b==0) return 1;
	if(b==1) return a%p;
	int c=ksm(a,b/2,p);
	c=c*c%p;
	if(b%2==1) c=c*a%p;
	return c%p;	
}
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
int yin[1000005];
signed main()
{
	//freopen("filename.in", "r", stdin);
	//freopen("filename.out", "w", stdout);
	int n=read();
	for(int d=1;d<=n;d++){
		for(int j=d;j<=n;j+=d){
			yin[j]+=d;
		}
	}
	int ans=n-1;
	cout<<ans<<' ';
	for(int i=2;i<=n;i++){
		ans+=n-yin[i];
		cout<<ans<<' ';
	}
	cout<<'\n';
	return 0;
}

T6 Jamie and Tree

换根+树链剖分+分讨+线段树

考虑求LCA

T7 XOR Tree

一条路径异或和为0

等价于du ^ dv ^ a_lca(u,v)=0

du表示u~rt的路径

开set维护查找即可

树上启发式合并可降复杂度至nlogn

即先合并轻儿子

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<bits/stdc++.h>
#define int long long
#define jiaa(a,b) {a+=b;if(a>=MOD) a-=MOD;}
#define jian(a,b) {a-=b;if(a<0) a+=MOD;}
using namespace std;
int ksm(int a,int b,int p){
	if(b==0) return 1;
	if(b==1) return a%p;
	int c=ksm(a,b/2,p);
	c=c*c%p;
	if(b%2==1) c=c*a%p;
	return c%p;	
}
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
int n;
int a[200005];
vector<int> tu[200005];
int ans,d[200005];
set<int> val[200005];
void dfs(int u,int fa){
	d[u]=d[fa]^a[u];
	val[u].insert(d[u]);
	bool fl=0;
	for(auto ed:tu[u]){
		if(ed==fa) continue;
		dfs(ed,u);
		if(val[u].size()<val[ed].size()) swap(val[u],val[ed]);
		for(auto v:val[ed]){
			if(val[u].find(v^a[u])!=val[u].end()){
				fl=1;
			}
		}
		for(auto v:val[ed]) val[u].insert(v);
	}
	if(fl){
		ans++;
		val[u].clear();
	}
}
signed main()
{
	//freopen("filename.in", "r", stdin);
	//freopen("filename.out", "w", stdout);
	n=read();
	for(int i=1;i<=n;i++) a[i]=read();
	for(int i=1;i<n;i++){
		int u=read(),v=read();
		tu[u].push_back(v);
		tu[v].push_back(u);
	}
	dfs(1,0);
	cout<<ans<<'\n';
	return 0;
}

T8 Nikita and game

找到一个连续段

维护其左侧和右侧的树的直径的端点

对加入的节点

去计算到l,r的距离

判断能否成为直径即可

T9 New Year Tree

发现每次加点最多贡献1

维护直径端点

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<bits/stdc++.h>
#define int long long
#define jiaa(a,b) {a+=b;if(a>=MOD) a-=MOD;}
#define jian(a,b) {a-=b;if(a<0) a+=MOD;}
using namespace std;
int ksm(int a,int b,int p){
	if(b==0) return 1;
	if(b==1) return a%p;
	int c=ksm(a,b/2,p);
	c=c*c%p;
	if(b%2==1) c=c*a%p;
	return c%p;	
}
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
vector<int> tu[1000010];
int dep[1000010],f[1000010][25];
void dfs(int x,int fa){
	dep[x]=dep[fa]+1;
	for(int i=0;i<=20;i++){
		f[x][i+1]=f[f[x][i]][i];
	}
	for(auto ed:tu[x]){
		if(ed==fa) continue;
		f[ed][0]=x;
		dfs(ed,x);
	}
}
int lca(int x,int y){
	if(dep[x]>dep[y]) swap(x,y);
	for(int i=20;i>=0;i--){
		if(dep[f[y][i]]>=dep[x]) y=f[y][i];
	}
	if(x==y) return x;
	for(int i=20;i>=0;i--){
		if(f[x][i]!=f[y][i]){
			x=f[x][i];
			y=f[y][i];
		}
	}
	return f[y][0];
}
signed main()
{
	//freopen("filename.in", "r", stdin);
	//freopen("filename.out", "w", stdout);
	tu[1].push_back(2);
	tu[1].push_back(3);
	tu[1].push_back(4);
	tu[2].push_back(1);
	tu[3].push_back(1);
	tu[4].push_back(1);
	dfs(1,0);
	int cnt=4;
	int maxx=2;
	int l=2,r=3;
	int q=read();
	while(q--){
		int u=read();
		tu[u].push_back(++cnt);
		tu[cnt].push_back(u);
		tu[u].push_back(++cnt);
		tu[cnt].push_back(u);
		dfs(u,f[u][0]);
		int an1=dep[l]+dep[cnt]-dep[lca(l,cnt)]*2;
		int an2=dep[r]+dep[cnt]-dep[lca(r,cnt)]*2;
		if(an1>maxx||an2>maxx){
			if(an1>maxx) r=cnt;
			else l=cnt;
			maxx=max(an1,an2);
		}
		cout<<maxx<<'\n';
	}
	return 0;
}

T10 [NordicOI 2025] 垃圾收集 / Garbage Collection

扫描线+线段树

扫描线板子

T11 [NOISG 2020 Finals] Progression

可直接维护

难写!!!

不如差分

做完了

T12 Legacy

线段树优化建图

开两棵线段树:出树/入树

一棵外向树,一棵内向树

两颗线段树所有叶节点连0的边

互相可达

现考虑区间连区间

每次建新的中转点

posted @ 2025-08-18 10:26  gbrrain  阅读(2)  评论(0)    收藏  举报