1 条题解
-
0
自动搬运
来自洛谷,原作者为

xudaxia
**搬运于
2025-08-24 21:46:02,当前版本为作者最后更新于2018-12-31 08:23:07,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
[CQOI2015]任务查询系统
一开始受到HNOI2015摘果子的启发写了一发树套树,然后就T了这题要求求覆盖一个点的前k小区间和。强制在线。
但主席树的解法其实差不多,因为主席树有前缀和的思想,我们把每一个区间拆开,在处加区间的权值,在处减区间的权值,然后用主席树维护一个前缀和。
我们就可以单点查询了。在主席树上二分就行了。#include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<algorithm> #include<vector> using namespace std; const int N=1e5+10; int read(){ int sum=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=getchar();} return sum*f; } int n,m,num,tot; int a[N],b[N],root[N<<6]; long long ans=1; struct tree { long long sum; int cnt,l,r; }t[N<<6]; vector<int>be[N],ed[N]; void update(int &u,int l,int r,int pre,int pos,int v){ u=++tot; t[u]=t[pre]; t[u].cnt+=v, t[u].sum+=1ll*v*b[pos]; if(l==r) return; int mid=(l+r)>>1; if(pos<=mid) update(t[u].l,l,mid,t[pre].l,pos,v); else update(t[u].r,mid+1,r,t[pre].r,pos,v); } long long query(int u,int l,int r,int k){ int num=t[t[u].l].cnt; if(l==r) return t[u].sum/(1ll*t[u].cnt)*1ll*k; int mid=(l+r)>>1; if(k<=num) return query(t[u].l,l,mid,k); else return query(t[u].r,mid+1,r,k-num)+t[t[u].l].sum; } int main(){ m=read(),n=read(); for(int i=1;i<=m;i++) { int x=read(),y=read(); a[i]=read(),b[i]=a[i]; be[x].push_back(i), ed[y+1].push_back(i); } sort(b+1,b+1+m); int num=unique(b+1,b+1+m)-b-1; for(int i=1;i<=n;i++) { root[i]=root[i-1]; for(int j=0;j<be[i].size();j++) { int p=lower_bound(b+1,b+1+num,a[be[i][j]])-b; update(root[i],1,num,root[i],p,1); } for(int j=0;j<ed[i].size();j++) { int p=lower_bound(b+1,b+1+num,a[ed[i][j]])-b; update(root[i],1,num,root[i],p,-1); } } for(int i=1;i<=n;i++) { int x=read(),a=read(),b=read(),c=read(),k=(1ll*a*ans+b)%c+1; if(k>t[root[x]].cnt) ans=t[root[x]].sum; else ans=query(root[x],1,num,k); printf("%lld\n",ans); } return 0; }
- 1
信息
- ID
- 2241
- 时间
- 2000ms
- 内存
- 512MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者