Codeforces 1479 D Odd Mineral Resource

本文介绍了如何通过树上莫队算法优化查询路径信息,同时处理修改操作的困难,外层套分块策略。另一种解决方案是采用随机化方法,利用矿物标签的异或特性判断路径中奇数矿物的存在概率,结合值域主席树实现高效查询。两种方法的时间复杂度和空间复杂度对比鲜明。

题面
此题树上不带修,查询路径信息,时限较长,可以树上莫队。利用树上莫队的传统方法,先树分块,对询问排序,然后再执行类似普通莫队的操作即可。但这里的修改操作并不好处理,于是在外层套一分块。每次修改就先修改单点的奇偶性,再修改块内奇数的总数。查询时用普通分块查询方法即可。
时间复杂度 O ( ( n + q ) n ) O((n+q) \sqrt{n}) O((n+q)n ),空间复杂度 O ( n + q ) O(n+q) O(n+q)

#include<stdio.h>
#include<algorithm>
#include<vector>
using namespace std;
#define R register int
#define L long long
#define I inline
#define N 300001
#define S 550
vector<int>G[N];
int a[N],pos[600001],b[546],dep[N],in[N],out[N],ans[N],h[N],ct[N],f[N],Top[N],sz[N];
bool tag[N],vc[N];
struct Query{
	int lf,rt,Start,End,id,Ql,Qr;
	I friend bool operator<(Query x,Query y){
		if(x.lf/S!=y.lf/S){
			return x.lf<y.lf;
		}
		return x.rt<y.rt;
	}
}q[N];
I void PreDFS(R x,R F,int&ct){
	ct++;
	pos[ct]=x;
	sz[x]=1;
	in[x]=ct;
	dep[x]=dep[F]+1;
	f[x]=F;
	for(vector<int>::iterator T=G[x].begin();T!=G[x].end();T++){
		if(*T!=F){
			PreDFS(*T,x,ct);
			sz[x]+=sz[*T];
			if(sz[*T]>sz[h[x]]){
				h[x]=*T;
			}
		}
	}
	ct++;
	out[x]=ct;
	pos[ct]=x;
}
I void ReDFS(R x,R t){
	Top[x]=t;
	if(h[x]!=0){
		ReDFS(h[x],t);
		for(vector<int>::iterator T=G[x].begin();T!=G[x].end();T++){
			if(*T!=f[x]&&*T!=h[x]){
				ReDFS(*T,*T);
			}
		}
	}
}
I int LCA(R x,R y){
	while(Top[x]!=Top[y]){
		if(dep[Top[x]]>dep[Top[y]]){
			x=f[Top[x]];
		}else{
			y=f[Top[y]];
		}
	}
	return dep[x]<dep[y]?x:y;
}
I void Add(int x){
	vc[x]^=true;
	if(vc[x]==true){
		b[x/S]++;
	}else{
		b[x/S]--;
	}
}
I int GetAns(int l,int r){
	int bl=l/S,br=r/S;
	if(bl==br){
		for(R i=l;i<=r;i++){
			if(vc[i]==true){
				return i;
			}
		}
		return-1;
	}
	for(R i=bl+1;i!=br;i++){
		if(b[i]!=0){
			for(R j=i*S;j!=(i+1)*S;j++){
				if(vc[j]==true){
					return j;
				}
			}
		}
	}
	for(R i=l;i!=(bl+1)*S;i++){
		if(vc[i]==true){
			return i;
		}
	}
	for(R i=br*S;i<=r;i++){
		if(vc[i]==true){
			return i;
		}
	}
	return-1;
}
int main(){
	int n,m,x,y;
	scanf("%d%d",&n,&m);
	for(R i=1;i<=n;i++){
		scanf("%d",a+i);
	}
	for(R i=1;i!=n;i++){
		scanf("%d%d",&x,&y);
		G[x].push_back(y);
		G[y].push_back(x);
	}
	x=0;
	PreDFS(1,0,x);
	ReDFS(1,1);
	for(R i=0;i!=m;i++){
		scanf("%d%d%d%d",&q[i].Start,&q[i].End,&q[i].Ql,&q[i].Qr);
		R st=q[i].Start,ed=q[i].End;
		R t=LCA(st,ed);
		q[i].id=i;
		if(t==st){
			q[i].lf=in[t];
			q[i].rt=in[ed];
		}else if(t==ed){
			q[i].lf=in[t];
			q[i].rt=in[st];
		}else if(out[st]<in[ed]){
			q[i].lf=out[st];
			q[i].rt=in[ed];
		}else{
			q[i].lf=out[ed];
			q[i].rt=in[st];
		}
	}
	sort(q,q+m);
	R l=1,r=0;
	for(R i=0;i!=m;i++){
		R tem,curr=q[i].rt,curl=q[i].lf;
		while(r<curr){
			r++;
			tem=pos[r];
			Add(a[tem]);
			tag[tem]^=true;
		}
		while(l>curl){
			l--;
			tem=pos[l];
			Add(a[tem]);
			tag[tem]^=true;
		}
		while(r>curr){
			tem=pos[r];
			Add(a[tem]);
			tag[tem]^=true;
			r--;
		}
		while(l<curl){
			tem=pos[l];
			Add(a[tem]);
			tag[tem]^=true;
			l++;
		}
		R lca=LCA(q[i].Start,q[i].End);
		if(lca!=q[i].Start&&q[i].End!=lca){
			Add(a[lca]);
			ans[q[i].id]=GetAns(q[i].Ql,q[i].Qr);
			Add(a[lca]);
		}else{
			ans[q[i].id]=GetAns(q[i].Ql,q[i].Qr);
		}
	}
	for(R i=0;i!=m;i++){
		printf("%d\n",ans[i]);
	}
	return 0;
}

莫队虽然勉强可过,但效率不高。此题可以采用随机化的算法。给每种矿物一个随机标签,若路径上属于给定区间的标签异或和不为 0 0 0,则一定有个数为奇数的矿物;若异或和为 0 0 0,则只有极小的概率存在个数为奇数的矿物。于是对原树建值域主席树,每次询问查询区间异或和即可。
时间复杂度 O ( ( n + q ) log ⁡ 2 n ) O((n+q) \log_2n) O((n+q)log2n),空间复杂度 O ( n log ⁡ 2 n ) O(n \log_2n) O(nlog2n)

#include<stdio.h>
#include<vector>
#include<algorithm>
#include<time.h>
using namespace std;
#define R register int
#define L long long
#define I inline
#define N 300001
struct SegmentNode{
	int Ls,Rs;
	L XorSum;
}t[9999999];
int a[N],f[N],h[N],sz[N],dep[N],Top[N],ct;
I void GetNode(int&x){
	ct++;
	x=ct;
}
L v[N];
I void Insert(int p1,int p2,int lf,int rt,const int x){
	t[p2].XorSum=v[x]^t[p1].XorSum;
	if(lf!=rt){
		int mid=lf+rt>>1;
		if(x>mid){
			GetNode(t[p2].Rs);
			t[p2].Ls=t[p1].Ls;
			Insert(t[p1].Rs,t[p2].Rs,mid+1,rt,x);
		}else{
			GetNode(t[p2].Ls);
			t[p2].Rs=t[p1].Rs;
			Insert(t[p1].Ls,t[p2].Ls,lf,mid,x);
		}
	}
}
I int GetAns(int p1,int p2,int p3,int p4,int lf,int rt,const int l,const int r){
	if(l<=lf&&rt<=r&&(t[p1].XorSum^t[p2].XorSum^t[p3].XorSum^t[p4].XorSum)==0){
		return-1;
	}
	if(lf==rt){
		return rt;
	}
	int mid=lf+rt>>1,q=-1;
	if(l<=mid){
		q=GetAns(t[p1].Ls,t[p2].Ls,t[p3].Ls,t[p4].Ls,lf,mid,l,r);
	}
	if(q==-1&&r>mid){
		return GetAns(t[p1].Rs,t[p2].Rs,t[p3].Rs,t[p4].Rs,mid+1,rt,l,r);
	}
	return q;
}
I L GetRand(){
	return(L)rand()<<45|(L)rand()<<30|rand()<<15;
}
vector<int>G[N];
I void PreDFS(int x,int F,int&n){
	dep[x]=dep[F]+1;
	f[x]=F;
	sz[x]=1;
	Insert(F,x,1,n,a[x]);
	for(vector<int>::iterator T=G[x].begin();T!=G[x].end();T++){
		if(*T!=F){
			PreDFS(*T,x,n);
			sz[x]+=sz[*T];
			if(sz[*T]>sz[h[x]]){
				h[x]=*T;
			}
		}
	}
}
I void ReDFS(int x,int t){
	Top[x]=t;
	if(h[x]!=0){
		ReDFS(h[x],t);
		for(vector<int>::iterator T=G[x].begin();T!=G[x].end();T++){
			if(*T!=f[x]&&*T!=h[x]){
				ReDFS(*T,*T);
			}
		}
	}
}
I int GetLCA(int x,int y){
	while(Top[x]!=Top[y]){
		if(dep[Top[x]]>dep[Top[y]]){
			x=f[Top[x]];
		}else{
			y=f[Top[y]];
		}
	}
	return dep[x]<dep[y]?x:y;
}
int main(){
	int n,q,x,y,l,r,z;
	scanf("%d%d",&n,&q);
	ct=n;
	srand((int)time(0));
	for(R i=1;i<=n;i++){
		scanf("%d",a+i);
		v[i]=GetRand();
	}
	for(R i=1;i!=n;i++){
		scanf("%d%d",&x,&y);
		G[x].push_back(y);
		G[y].push_back(x); 
	}
	PreDFS(1,0,n);
	ReDFS(1,1);
	for(R i=0;i!=q;i++){
		scanf("%d%d%d%d",&x,&y,&l,&r);
		z=GetLCA(x,y);
		printf("%d\n",GetAns(x,y,z,f[z],1,n,l,r));
	}
	return 0;
}
### Codeforces 1487D Problem Solution The problem described involves determining the maximum amount of a product that can be created from given quantities of ingredients under an idealized production process. For this specific case on Codeforces with problem number 1487D, while direct details about this exact question are not provided here, similar problems often involve resource allocation or limiting reagent type calculations. For instance, when faced with such constraints-based questions where multiple resources contribute to producing one unit of output but at different ratios, finding the bottleneck becomes crucial. In another context related to crafting items using various materials, it was determined that the formula `min(a[0],a[1],a[2]/2,a[3]/7,a[4]/4)` could represent how these limits interact[^1]. However, applying this directly without knowing specifics like what each array element represents in relation to the actual requirements for creating "philosophical stones" as mentioned would require adjustments based upon the precise conditions outlined within 1487D itself. To solve or discuss solutions effectively regarding Codeforces' challenge numbered 1487D: - Carefully read through all aspects presented by the contest organizers. - Identify which ingredient or component acts as the primary constraint towards achieving full capacity utilization. - Implement logic reflecting those relationships accurately; typically involving loops, conditionals, and possibly dynamic programming depending on complexity level required beyond simple minimum value determination across adjusted inputs. ```cpp #include <iostream> #include <vector> using namespace std; int main() { int n; cin >> n; vector<long long> a(n); for(int i=0;i<n;++i){ cin>>a[i]; } // Assuming indices correspond appropriately per problem statement's ratio requirement cout << min({a[0], a[1], a[2]/2LL, a[3]/7LL, a[4]/4LL}) << endl; } ``` --related questions-- 1. How does identifying bottlenecks help optimize algorithms solving constrained optimization problems? 2. What strategies should contestants adopt when translating mathematical formulas into code during competitive coding events? 3. Can you explain why understanding input-output relations is critical before implementing any algorithmic approach? 4. In what ways do prefix-suffix-middle frameworks enhance model training efficiency outside of just tokenization improvements? 5. Why might adjusting sample proportions specifically benefit models designed for tasks requiring both strong linguistic comprehension alongside logical reasoning skills?
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值