2025牛客寒假算法基础集训营补题
2025牛客寒假算法基础集训营1
H 井然有序之窗
做法:贪心
先把区间按左端点排序,对于数
无解情况:当该右端点最小的区间的右端点小于
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N=100005;
LL n,m,t,cnt=1,l=1,ans[N];
struct node{
LL l,r,i;
bool operator < (const node& a) const {
return r>a.r;
}
}a[N],b;
priority_queue<node> q;
inline LL read(){
LL s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+ch-'0';ch=getchar();}
return s*w;
}
bool cmp(node a, node b){
if(a.l==b.l) return a.r-a.l<b.r-b.l;
else return a.l<b.l;
}
int main(){
n=read();
for(int i=1;i<=n;i++){
a[i].l=read(),a[i].r=read(),a[i].i=i;
}
sort(a+1,a+1+n,cmp);
while(a[cnt].l<=l&&cnt<=n){
q.push(a[cnt++]);
}
while(!q.empty()){
b=q.top();q.pop();
if(b.r<l){
printf("-1\n");return 0;
}
ans[b.i]=l;
l++;
while(a[cnt].l<=l&&cnt<=n){
q.push(a[cnt++]);
}
}
if(cnt<=n){
printf("-1\n");
}else{
for(int i=1;i<=n;i++){
printf("%lld ",ans[i]);
}
}
return 0;
}
F 双生双宿之探
做法:双指针、前缀和
因为一个合法区间只含有两个数,故可将其变为 1 与 -1
1 | 4 | 1 | 1 | 4 | 3 | 3 | 4 | 2 | 2 |
---|---|---|---|---|---|---|---|---|---|
1 | -1 | 1 | 1 | -1 | 1 | 1 | -1 | 1 | 1 |
之后使用前缀和
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N=100005;
LL n,m,t;
inline LL read(){
LL s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+ch-'0';ch=getchar();}
return s*w;
}
void solve(){
n=read();
vector<LL> a(n),v(n),f(n+1),k(n);
for(int i=0;i<n;i++){
v[i]=a[i]=read();
}
sort(v.begin(),v.end());
unique(v.begin(),v.end());
for(int i=0;i<n;i++){
a[i]=lower_bound(v.begin(),v.end(),a[i])-v.begin();
}//离散化,用桶统计元素种类
f[0]=1;
for(int i=1;i<n;i++){
if(a[i]==a[i-1]){
f[i]=f[i-1];
}else{
f[i]=-f[i-1];
}
}
LL dist=0,ans=0;
vector<LL> pre(n+1),cnt(2*n+1);
pre[0]=n;
for(int i=1;i<n;i++){
pre[i+1]=pre[i]+f[i];
}//前缀和加n,方便计数
for(int l=0,r=1;r<=n;r++){
cnt[pre[r-1]]++;
dist+=(k[a[r-1]]++==0);
while(dist>2){
cnt[pre[l]]--;
dist-=(k[a[l]]--==0);
l++;
}
ans+=cnt[pre[r]];
}
printf("%lld\n",ans);
return ;
}
int main(){
t=read();
while(t--){
solve();
}
return 0;
}
K 硝基甲苯之魇
做法:数论,线段树,ST表,二分,map
对于区间 gcd 有这样一个性质,则当左端点
20 | 8 | 4 | 6 | 2 | 3 | 5 | 6 | 7 | 5 | a[] |
---|---|---|---|---|---|---|---|---|---|---|
20 | 4 | 4 | 2 | 2 | 1 | 1 | 1 | 1 | 1 | gcd |
所以当
对于区间异或和,我们可以通过异或前缀和来计算。
在查找这一段区间 gcd 有没有相等的区间异或和时。
因为
我们可以通过
#include<bits/stdc++.h>
#define LL int
#define l(p) tree[p].l
#define r(p) tree[p].r
#define gd(p) tree[p].gd
using namespace std;
const int N=200005;
LL gcd(LL a,LL b);
LL n,m,t,k,a[N];
struct Segment_tree{
LL l,r,gd;
}tree[N*4];
inline LL read(){
LL s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+ch-'0';ch=getchar();}
return s*w;
}
LL gcd(LL a,LL b){
return b?gcd(b,a%b):a;
}
void pushup(LL p){
gd(p)=gcd(gd(p<<1),gd(p<<1|1));
return ;
}
void build(LL p,LL l,LL r){
l(p)=l,r(p)=r;
if(l==r){
gd(p)=a[l];
return ;
}
LL mid=(l+r)>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
pushup(p);
return ;
}
LL query(LL p,LL l,LL r){
if(l(p)>=l&&r(p)<=r){
return gd(p);
}
LL mid=(l(p)+r(p))>>1;
if(r<=mid) return query(p<<1,l,r);
else{
if(l>mid) return query(p<<1|1,l,r);
else{
LL val=gcd(query(p<<1,l,r),query(p<<1|1,l,r));
return val;
}
}
return 0;
}
void solve(){
n=read();
vector<LL> pre(n+1);
unordered_map<LL,vector<LL>> mp;//注意这里因为常数过大,使用map时会超时,而使用unordered_map则不会
for(int i=1;i<=n;i++){
a[i]=read();
pre[i]=pre[i-1]^a[i];
mp[pre[i]].push_back(i);
}
build(1,1,n);
LL ans=0;
for(int i=1;i<=n;i++){
LL L=i,g=a[i];
while(L<=n){
LL l=L,r=n;
while(l<r){
LL mid=(l+r+1)>>1;
if(query(1,i,mid)==g) l=mid;
else r=mid-1;
}
LL d=g^pre[i-1];
if(L!=i)
ans+=upper_bound(mp[d].begin(),mp[d].end(),r)-lower_bound(mp[d].begin(),mp[d].end(),L);
else ans+=upper_bound(mp[d].begin(),mp[d].end(),r)-upper_bound(mp[d].begin(),mp[d].end(),L);
L=r+1;
g=query(1,i,r+1);
}
}
printf("%d\n",ans);
return ;
}
int main(){
t=read();
while(t--){
solve();
}
return 0;
}
2025牛客寒假算法基础集训营2
E 一起走很长的路!
做法:前缀和,线段树
分析可知每次操作只增加第
对于需要操作多少次,则通过预处理先求出。
再通过线段树维护数组
对于每次询问则找到数组
#include<bits/stdc++.h>
#define LL long long
#define l(p) tree[p].l
#define r(p) tree[p].r
#define ma(p) tree[p].ma
using namespace std;
const int N=200005;
LL n,m,t,k,a[N],pre[N],q,b[N];
struct Segment_tree{
LL l,r,ma;
}tree[N<<2];
inline LL read(){
LL s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+ch-'0';ch=getchar();}
return s*w;
}
void pushup(LL p){
ma(p)=max(ma(p<<1),ma(p<<1|1));
return ;
}
void build(LL p,LL l,LL r){
l(p)=l,r(p)=r,ma(p)=-9223372036854775808;
if(l==r){
ma(p)=b[l];
return ;
}
LL mid=(l+r)>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
pushup(p);
return ;
}
LL query(LL p,LL l,LL r){
if(l(p)>=l&&r(p)<=r){
return ma(p);
}
LL mid=(l(p)+r(p))>>1;
if(r<=mid) return query(p<<1,l,r);
else
if(l>mid) return query(p<<1|1,l,r);
else
return max(query(p<<1,l,r),query(p<<1|1,l,r));
}
void solve(){
n=read(),q=read();
for(int i=1;i<=n;i++){
a[i]=read();
pre[i]=pre[i-1]+a[i];
b[i]=a[i]-pre[i-1];
}
build(1,1,n);
for(int i=1;i<=q;i++){
LL l=read(),r=read();
if(l==r){
printf("0\n");
continue;
}
LL x=query(1,l+1,r);
x+=pre[l-1];
printf("%lld\n",max(x,0ll));
}
return ;
}
int main(){
t=1;//t=read();
while(t--){
solve();
}
return 0;
}
2025牛客寒假算法基础集训营3
G 智乃与模数
做法:整除分块,二分
整除分块结论
对于常数
成立且满足
而后对于每一个块内,
我们可以二分第
#include<bits/stdc++.h>
#define LL long long
#define l(p) tree[p].l
#define r(p) tree[p].r
#define ma(p) tree[p].ma
using namespace std;
const int N=200005;
LL n,m,t,k;
inline LL read(){
LL s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+ch-'0';ch=getchar();}
return s*w;
}
void solve(){
n=read(),k=read();
LL L=0,R=n,ans=0;
while(L<R){
LL mid=(L+R)>>1;
LL sum=0,a,b,x,tot=0,val=0;
for(int l=1,r;l<=n;){
r=n/(n/l);
a=n%l;
b=n/l;
x=0;
if(a>=mid){
x=ceil((a-mid)/b)+1;
if(a-(x-1)*b==mid){
val++;
}
}
sum+=x;
tot+=(a+a-(x-1)*b)*(x)/2;
l=r+1;
}
if(sum==k){
printf("%lld\n",tot);
return ;
}
if(sum>k){
if(sum-val<k){
printf("%lld\n",tot-(sum-k)*mid);
return ;
}
}
if(sum>k) L=mid+1;
else R=mid;
}
return ;
}
int main(){
t=1;//t=read();
while(t--){
solve();
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话