[2023四校联考3]sakuya 题解(根号分治)
题目链接。
题目分析
第一个操作类似哈希冲突那一道题,可以运用类似的思路开一个二维表,很容易想到两种做法:
-
开一个二维表,表上的第
行,第 列表示序列下标在模 意义下等于 的加法标记。对于修改操作,直接暴力修改对应的那一行的值即可,查询时用线段树查询那个区间的和,枚举每一行,用一个数据结构加上对应的加法标记即可。 -
线段树暴力修改区间。
设定一个数
但是第一种操作的常数感觉要爆炸,将表上的第
#include<bits/stdc++.h> using namespace std; inline long long read(){ long long 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<<1)+(x<<3)+(ch^48),ch=getchar(); return x*f; } const int maxn=2e5+20; long long n,m,a[maxn],len; struct node{ long long tag,sum; }tree[maxn<<2]; struct segment_tree{ inline long long ls(int x){ return x<<1; } inline long long rs(int x){ return x<<1|1; } inline void push_up(int p){ tree[p].sum=tree[ls(p)].sum+tree[rs(p)].sum; } void build(int p,int l,int r){ if(l==r){ tree[p].sum=a[l]; return; } int mid=l+r>>1; build(ls(p),l,mid); build(rs(p),mid+1,r); push_up(p); } inline void push_down(int p,int l,int r){ int mid=l+r>>1; tree[ls(p)].sum+=tree[p].tag*(mid-l+1),tree[rs(p)].sum+=tree[p].tag*(r-mid); tree[ls(p)].tag+=tree[p].tag,tree[rs(p)].tag+=tree[p].tag; tree[p].tag=0; } void update(int p,int l,int r,int x,int y,long long k){ if(x<=l&&r<=y){ tree[p].tag+=k,tree[p].sum+=k*(r-l+1); return; } push_down(p,l,r); int mid=l+r>>1; if(x<=mid) update(ls(p),l,mid,x,y,k); if(y>mid) update(rs(p),mid+1,r,x,y,k); push_up(p); } long long query(int p,int l,int r,int x,int y){ if(x<=l&&r<=y) return tree[p].sum; push_down(p,l,r); int mid=l+r>>1; if(y<=mid) return query(ls(p),l,mid,x,y); if(x>mid) return query(rs(p),mid+1,r,x,y); return query(ls(p),l,mid,x,y)+query(rs(p),mid+1,r,x,y); } }S; long long f[1000][1000]; inline void solve2(long long x,long long y,long long k){ if(x-1<=y) S.update(1,1,n,1,n,k); else for(int i=0;i<n;i+=x) S.update(1,1,n,i+1,min({n,i+y+1,i+x}),k); } inline void solve1(long long x,long long y,long long k){ for(int i=0;i<=min(y,x-1);i++) f[x][i]+=(i+1)*k; for(int i=y+1;i<x;i++) f[x][i]+=(min(y,x-1)+1)*k; } inline void solve3(long long x,long long y){ long long res=S.query(1,1,n,x,y); --x,--y; long long l,r; for(int i=1;i<=len;i++){ l=(long long)ceil(1.0*x/i)*i-x,r=y-(long long)floor(1.0*y/i)*i; res+=f[i][i-1]-f[i][i-l-1],res+=f[i][r]; res+=f[i][i-1]*((y/i)-(long long)ceil(1.0*x/i)); } printf("%lld\n",res); } int main(){ n=read(),m=read(); len=990; for(int i=1;i<=n;i++) a[i]=read(); S.build(1,1,n); long long op,x,y,k; for(int j=1;j<=m;j++){ op=read(),x=read(),y=read(); if(op==1) k=read(); if(op==1&&x<=len) solve1(x,y,k); else if(op==1&&x>len) solve2(x,y,k); else if(op==2) solve3(x,y); } return 0; }
本文作者:dayz_break
本文链接:https://www.cnblogs.com/dayz-break/p/18440810
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步