pyyzDay3

基础算法

T1 CF1783E Game of the Year

image

#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 a[200005],b[200005],sum[200005],ans[200005];
void solve(){
	int n=read();
	for(int i=1;i<=n;i++) a[i]=read();
	for(int i=1;i<=n;i++) b[i]=read();
	memset(sum,0,sizeof(sum));
	for(int i=1;i<=n;i++){
		if(b[i]>=a[i]) continue;
		sum[b[i]]++;
		sum[a[i]]--;
	}
	for(int i=1;i<=n;i++){
		sum[i]+=sum[i-1];
	}
	int cnt=0;
	for(int k=1;k<=n;k++){
		int f=0;
		for(int i=k;i<=n;i+=k){
			if(sum[i]){
				f=1;
				break;
			}
		}
		if(!f) ans[++cnt]=k;
	}
	cout<<cnt<<'\n';
	for(int i=1;i<=cnt;i++){
		cout<<ans[i]<<' ';
	}
	cout<<'\n';
}
signed main()
{
	//freopen("filename.in", "r", stdin);
	//freopen("filename.out", "w", stdout);
	int T=read();
	while(T--){
		solve();
	}
	return 0;
}

T2 [NOI Online 2021 入门组] 重力球

image

T3 CF1307D Cow and Fields

image

T4 CF715B Complete The Graph

image

image

倍增

T1 Genius Acm

image

image

image

#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 a[500005],sec[25],p[500005],pp[500005],n,m,k;
bool check(int L,int mid,int R){
	for(int i=mid;i<R;i++) p[i]=a[i];
	sort(p+mid,p+R);
	int lp=L,rp=mid;
	int cnt_pp=0;
	while(lp<mid&&rp<R){
		if(p[lp]<=p[rp]){
			pp[cnt_pp++]=p[lp];
			lp++;
		}
		else{
			pp[cnt_pp++]=p[rp];
			rp++;
		}
	}
	while(lp<mid){
		pp[cnt_pp++]=p[lp];
		lp++;
	}
	while(rp<R){
		pp[cnt_pp++]=p[rp];
		rp++;
	}
	int ans=0;
	for(int i=0;i<min(m,cnt_pp);i++,cnt_pp--){
		ans+=(pp[i]-pp[cnt_pp-1])*(pp[i]-pp[cnt_pp-1]);
		if(ans>k) return false;
	}
	return true;
}
void solve(){
	n=read(),m=read(),k=read();
	for(int i=0;i<n;i++) a[i]=read();
	int l=0,r=0,ans=0;
	while(r<n){
		int kk=1;
		while(kk){
			if(kk+r<=n&&check(l,r,kk+r)){
				r+=kk;
				kk<<=1;
				if(r>n) break;
				for(int i=l;i<r+kk;i++){
					p[i]=pp[i-l];
				}
			}
			else kk>>=1;
		}
		ans++;
		l=r;
	}
	cout<<ans<<'\n';
}
signed main()
{
	//freopen("filename.in", "r", stdin);
	//freopen("filename.out", "w", stdout);
	int T=read();
	sec[0]=1;
	for(int i=1;i<=20;i++) sec[i]=sec[i-1]*2;
	while(T--){
		solve();
	}
	return 0;
}

分治

T1 Tricky Function

image

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<bits/stdc++.h>
#define int long long
using namespace std;
struct node{
	int x,y;
}s[100005];
int tem[100005];
int a[100005],sum[100005];
bool cmp1(node i,node j){
	if(i.x==j.x) return i.y<j.y;
	return i.x<j.x;
}
bool cmp2(int i,int j){
	return s[i].y<s[j].y;
}
int dis(int i,int j){
	return (s[i].x-s[j].x)*(s[i].x-s[j].x)+(s[i].y-s[j].y)*(s[i].y-s[j].y);
}
int merge(int l,int r){
	int an=10000000000;
	if(l==r) return an;
	if(l+1==r) return dis(l,r);
	int mid=(l+r)/2;
	an=merge(l,mid);
	an=min(an,merge(mid+1,r));
	int k=0;
	for(int i=l;i<=r;i++){
		if(abs(s[mid].x-s[i].x)*abs(s[mid].x-s[i].x)<an){//平方缩小枚举范围
			tem[++k]=i;
		}
	}
	sort(tem+1,tem+k+1,cmp2);
	for(int i=1;i<=k;i++){
		for(int j=i+1;j<=k&&(s[tem[j]].y-s[tem[i]].y)*(s[tem[j]].y-s[tem[i]].y)<an;j++){//平方缩小枚举范围
			int sum=dis(tem[i],tem[j]);
			if(an>sum) an=sum;
		}
	}
	return an;
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		sum[i]=sum[i-1]+a[i];
	}
	for(int i=1;i<=n;i++){
		s[i].x=i;
		s[i].y=sum[i];
	}
	sort(s+1,s+n+1,cmp1);
	int ans=merge(1,n);
	cout<<ans<<'\n';
	return 0;
}

T2 [NOI2023] 贸易

image

困难题:迷宫守卫

压位

T1 [NOI2017] 整数

image

T2 分流器

简要题意
有一个分流器系统,它包含 n + 1 个节点,编号为 1 ∼ n + 1。
除节点 n + 1 外,每个节点的出度都 = 2。节点 i(1 ≤ i ≤ n)
的出边连向的节点的编号 outi,0, outi,1 ∈ (i, n + 1]。
节点 i(1 ≤ i ≤ n)有一个布尔变量 bi。在节点 1 放入一个物品
后,记物品当前位于节点 p,分流器会按以下规则运作:

  1. 若 p = n + 1,物品离开分流器,运作结束。
  2. 记 q = bp,令 bp ← ¬bp,令 p ← outp,q,返回第 1 步。
    上一个物品未离开分流器时,下一个物品不会被放入。记放入 t
    个物品后节点 1 ∼ n 的布尔变量状态序列为 St。给定 S0,求最
    小的正整数 T 满足 ST = S0,或报告无解。
    n ≤ 50000。

image

字符串

T1 [CSP-S 2023] 消消乐

考虑括号匹配

对于一个字符串,把它的字符依次加入栈内,若字符和栈顶相同则把它们都弹出,最后字符串可消除等价于栈是空的

考虑对整个字符串做这样的匹配,注意到子串 [l, r] 可消除等价于加完 l − 1 时的栈内状态和加完 r 时的相同。栈内状态可看作字符串,维护各哈希值(注意要能区分长度)的出现次数即可

image

#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 dp[2000005];
int h[2000005][30];
int g[2000005];
signed main()
{
	//freopen("filename.in", "r", stdin);
	//freopen("filename.out", "w", stdout);
	int n=read();
	string s;
	cin>>s;
	string T=" ";
	T+=s;
	int ans=0;
	for(int i=1;i<=n;i++){
		g[i]=i;
		int p=h[g[i-1]][T[i]-'a'+1];
		if(p){
			g[i]=g[p-1];
			dp[i]=dp[p-1]+1;
		}
		h[g[i]][T[i]-'a'+1]=i;
		ans+=dp[i];
	}
	cout<<ans<<'\n';
	return 0;
}

T2

image

image

Hash

T1 [国家集训队] 等差子序列

image

T2 [ONTAK2015] Bajtocja

image

T3 [CSP-S 2022] 星战

image

集合hash

#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;
}
const int MOD=998244353;
const int base=31;
vector<int> tu[500005];
int h[500005],cnt,sum[500005],del[500005];
signed main()
{
	//freopen("filename.in", "r", stdin);
	//freopen("filename.out", "w", stdout);
	int n=read(),m=read();
	srand(time(0));
	int su=0,goal=0;
	for(int i=1;i<=n;i++){
		h[i]=(rand()*rand()%MOD+rand())%MOD;
		goal+=h[i];
	}
	for(int i=1;i<=m;i++){
		int u=read(),v=read();
		tu[u].push_back(v);
		sum[v]+=h[u];
		su+=h[u];
	}
	int q=read();
	while(q--){
		int opt=read(),u=read();
		if(opt==1){
			int v=read();
			su-=h[u];
			del[v]+=h[u];
			sum[v]-=h[u];
		}
		if(opt==2){
			su-=sum[u];
			del[u]+=sum[u];
			sum[u]=0;
		}
		if(opt==3){
			int v=read();
			su+=h[u];
			del[v]-=h[u];
			sum[v]+=h[u];
		}		
		if(opt==4){
			su+=del[u];
			sum[u]+=del[u];
			del[u]=0;
		}
		if(su==goal) cout<<"YES"<<'\n';
		else cout<<"NO"<<'\n';
	}
	return 0;
}

T4 [NOI2024] 集合

image

posted @ 2025-08-06 10:46  gbrrain  阅读(3)  评论(0)    收藏  举报