小秦种树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 三足鼎立
使用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 整除光棍
模拟除法过程。由于数据范围过大,需要逐位模拟;且商要存在字符串中。
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;
}