2026.4.4

小秦种树2

与第一题相比,多了对数字取模的操作(先取模再加和)。使用的方法是:维护tree数组的同时,维护treemax数组,build和update时进行同步操作。

cpp 复制代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
#define N 100005
int n,m,num[N],x,y,z,ans,p,len=0;
int tree[4*N],treemax[4*N];
void build(int x,int l,int r)
{
	len=max(len,x);
	if(l==r)
	{
		tree[x]=num[l];
		treemax[x]=num[l];
		return ;
	}
	int mid=(l+r)/2;
	build(x*2,l,mid);
	build(x*2+1,mid+1,r);
	tree[x]=tree[2*x]+tree[2*x+1];
	treemax[x]=max(treemax[2*x],treemax[2*x+1]);
	return ;
}
void find(int xx,int l,int r,int x,int y)
{
	if(x<=l&&y>=r)
	{
		ans+=tree[xx];
		return ;
	}
	int mid=(l+r)/2;
	if(mid>=x)
		find(xx*2,l,mid,x,y);
	if(mid+1<=y)
		find(xx*2+1,mid+1,r,x,y);
	return ;
}
void update(int xx,int l,int r,int x,int y,int p)
{
	if(treemax[xx]<p)
		return ;
	if(l==r)
	{
		tree[xx]%=p;
		treemax[xx]=tree[xx];
		return ;
	}
	int mid=(l+r)/2;
	if(mid>=x)
		update(xx*2,l,mid,x,y,p);
	if(y>=mid+1)
		update(xx*2+1,mid+1,r,x,y,p);
	tree[xx]=tree[xx*2]+tree[xx*2+1];
	treemax[xx]=max(treemax[2*xx],treemax[2*xx+1]);
	return ;
	
}
void update2(int xx,int l,int r,int x,int y)
{
	if(l==r&&l==x)
	{
		tree[xx]=y;
		treemax[xx]=max(y,treemax[xx]);
		return ;
	}
	int mid=(l+r)/2;
	if(x<=mid)
		update2(xx*2,l,mid,x,y);
	else
		update2(xx*2+1,mid+1,r,x,y);
	tree[xx]=tree[xx*2]+tree[xx*2+1];
	treemax[xx]=max(treemax[2*xx],treemax[2*xx+1]);
	return ;
}
signed main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		cin>>num[i];
	build(1,1,n);
	for(int i=1;i<=m;i++)
	{
		cin>>x;
		if(x==1)
		{
			cin>>y>>z;
			ans=0;
			find(1,1,n,y,z);
			cout<<ans<<endl;
		}
		if(x==2)
		{
			cin>>y>>z>>p;
			update(1,1,n,y,z,p);
		}
		if(x==3)
		{
			cin>>y>>z;
			update2(1,1,n,y,z);
		}
	}
	return 0;
}

7-40 三足鼎立

https://pintia.cn/problem-sets/2037056710707339264/exam/problems/type/7?problemSetProblemId=2037056710849945638

使用sort+lowerbound和upperbound计算>=/>的第一个值,注意返回的是地址,时间复杂度lgN

int idx1=lower_bound(num+1+i,num+1+n,num1)-num;

int idx2=upper_bound(num+1+i,num+1+n,num2)-num;

idx2--;

if(idx1<=idx2)

ans+=idx2-idx1+1;

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define N 100004
int n,p,num[N],ans=0;
signed main()
{
	cin>>n>>p;
	for(int i=1;i<=n;i++)
		cin>>num[i];
	sort(num+1,num+1+n);	
	for(int i=1;i<=n;i++)
	{
		int x=num[i];
		int num1=p-x+1;
		int num2=p+x-1;
		int idx1=lower_bound(num+1+i,num+1+n,num1)-num;
		int idx2=upper_bound(num+1+i,num+1+n,num2)-num;
		idx2--;
		if(idx1<=idx2)
			ans+=idx2-idx1+1;
	}
	cout<<ans;
	return 0;
}

7-37 整除光棍

https://pintia.cn/problem-sets/2037056710707339264/exam/problems/type/7?problemSetProblemId=2037056710849945635

模拟除法过程。由于数据范围过大,需要逐位模拟;且商要存在字符串中。

div.push_back(digit+'0');

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
//#define int long long
signed main()
{
	int x;
	cin>>x;
	int mod=0,dig=0;
	bool fg=false;
	string div="";
	while(true)
	{
		mod=mod*10+1;
		int digit=mod/x;
		div.push_back(digit+'0');
		mod%=x;
		dig++;
		if(mod==0)
		{
			for(int i=0;i<div.size();i++)
			{
				if(div[i]=='0'&&fg==false)
					continue;
				fg=true;
				cout<<div[i];
			}
			cout<<" "<<dig;
			break;
		}
	}
	return 0;
}