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

Graphcity
循此苦旅,终抵繁星。搬运于
2025-08-24 22:31:12,当前版本为作者最后更新于2021-05-08 19:19:10,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
思路
我们不妨从最暴力的方法想一想,总共有 个询问需要 ,枚举 的 值需要 ,枚举 中的值需要 ,暴力计算 函数的值还要 ,总共 ,铁定超时。
显然那个 是不能够消除的,那我们考虑优化那三个 。
首先 在线 计算 函数可以用分块 或 ,但是前一种做法需要预处理前缀块的出现次数,空间复杂度 会被卡。而第二种做法时间复杂度太高,也会被卡。于是我们考虑主席树,时间复杂度 ,空间复杂度 ,刚刚好。现在时间复杂度被优化到了 。
接着,我们发现 与 之间只差了 对函数的贡献,而它不小于 0,最多为 1。也就是说, 到 之间的值必然 不下降,而且每相邻两个数相差 至多为 1。所以, ,又优化掉了一个 ,此时时间复杂度变为 。
现在时间复杂度瓶颈就变成了枚举 上。这个时候,我们就可以试着猜一猜求和符号右边的式子有什么规律了。事实上,求和符号右边的式子是 随着 的增大而增大 的。我们来证明一下:
当 时,右边的值为 ,而当 时,右边为 。两者的区别仅仅在于 产生的贡献。
- 当 在 不出现时, 和 分别会比 和 大 1,相当于没起到作用。
- 当 在 出现时, 和 和后面相比没有任何变化,相当于不起作用。
- 当 仅在 出现时, 相较后面没有变化,而 加上了 1,总共 减去了 1。
综上,证明成立,且 相较 时,值至多会增加 1。于是我们便可以愉快地二分了,总时间复杂度变成了 ,在有 O2 优化的情况下可以跑过去。
代码
#include<bits/stdc++.h> using namespace std; const int Maxn=3e5; inline int read() { char ch=getchar(); int f=1,x=0; while(ch>'9' || ch<'0') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*f; } struct Node{int l,r,siz;} t[Maxn*40+5]; int tot,rt[Maxn+5]; #define ls(x) t[x].l #define rs(x) t[x].r int n,m,lst,h[Maxn+5],cnt[Maxn+5],nxt[Maxn+5],Q[10]; vector<int> v; inline void Insert(int l,int r,int L,int &R,int val) { t[++tot]=t[L],R=tot,t[R].siz++; if(l==r) return; int mid=(l+r)>>1; if(val<=mid) Insert(l,mid,ls(L),ls(R),val); else Insert(mid+1,r,rs(L),rs(R),val); } inline int Find(int l,int r,int L,int R,int val) { if(l==r) return t[R].siz-t[L].siz; int mid=(l+r)>>1; if(val<=mid) return t[rs(R)].siz-t[rs(L)].siz+Find(l,mid,ls(L),ls(R),val); else return Find(mid+1,r,rs(L),rs(R),val); } inline int F(int l,int r) {return Find(1,n+1,rt[l-1],rt[r],r+1);} inline void Solve() { while(m--) { int a,b,c,d,e,f,l,r,siz=-1; for(int i=1;i<=4;++i) Q[i]=(read()+lst)%n+1; sort(Q+1,Q+5),a=Q[1],b=Q[2],c=Q[3],d=Q[4],e=read(),f=read(),l=a-1,r=b; while(l<r) { int mid=(l+r+1)/2; if(mid==a-1 || F(mid,d)-F(mid,c)+1<e) l=mid; else r=mid-1; } siz-=l,l=a,r=b+1; while(l<r) { int mid=(l+r)/2; if(mid==b+1 || F(mid,d)-F(mid,c)+1>f) r=mid; else l=mid+1; } siz+=l,lst=siz; printf("%d\n",siz); } } inline void Init() { n=read(),m=read(); for(int i=1;i<=n;++i) v.push_back(h[i]=read()),cnt[i]=n+1; sort(v.begin(),v.end()),v.erase(unique(v.begin(),v.end()),v.end()); for(int i=1;i<=n;++i) h[i]=lower_bound(v.begin(),v.end(),h[i])-v.begin()+1; for(int i=n;i>=1;--i) nxt[i]=cnt[h[i]],cnt[h[i]]=i; for(int i=1;i<=n;++i) Insert(1,n+1,rt[i-1],rt[i],nxt[i]); } int main() { Init(),Solve(); return 0; }
- 1
信息
- ID
- 6576
- 时间
- 4500ms
- 内存
- 256MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者