Interval(20年牛客多校5)
题意
有一个数列 长度为 ,
,
,
有 组询问,对于给定的 ,求 的大小,强制在线。
思路
考虑到固定一个右端点,左端点向左拓展的时候, 的个数不会很多,最多只有 个,于是我们就可以用二分预处理出所有的值。由于需要保留上一个版本的答案,所以我们需要拿一颗主席树来维护,第 个版本的线段树中第 个位置记录的是 是否对答案有贡献,这样就涉及了去重的这个问题。一个常见的技巧是对于一个值,只记录离第 个位置最近的那个位置,并将之前的位置删去,这样就可以保证一个值只被算一次了,所以这道题就被转换成了主席树上单点修改,区间查询。
代码
#include<bits/stdc++.h> using namespace std; #define ll long long #define fi first #define se second const double eps=1e-12; const int inf=0x3f3f3f3f; const ll INF=0x3f3f3f3f3f3f3f3f; const double pi=acos(-1.0); int dcmp(double x){if(fabs(x)<eps)return 0;return x>0?1:-1;} #define int ll struct president_segment_tree { int cnt=0; int root[100005]; struct node { int l,r,sum; }z[100005*600]; int clone(int x) { cnt++;z[cnt]=z[x]; return cnt; } void update(int id1,int &id2,int l,int r,int x,int w) { id2=clone(id1); z[id2].sum+=w; if(l==r)return; else { int mid=(l+r)>>1; if(x<=mid)update(z[id1].l,z[id2].l,l,mid,x,w); else update(z[id1].r,z[id2].r,mid+1,r,x,w); } } int query(int id,int l,int r,int x,int y) { // cout<<"query "<<id<<' '<<l<<' '<<r<<' '<<x<<' '<<y<<' '<<z[id].sum<<'\n'; if(x<=l&&r<=y)return z[id].sum; else { int mid=(l+r)>>1; int ans=0; if(x<=mid)ans+=query(z[id].l,l,mid,x,y); if(mid<y)ans+=query(z[id].r,mid+1,r,x,y); return ans; } } }pst; int a[100005]; struct segment_tree { int tree[100005<<2]; void build(int p,int l,int r) { if(l==r)tree[p]=a[l]; else { int mid=(l+r)>>1; build(p<<1,l,mid); build(p<<1|1,mid+1,r); tree[p]=tree[p<<1]&tree[p<<1|1]; } } int query(int p,int l,int r,int x,int y) { if(x<=l&&r<=y)return tree[p]; else { int mid=(l+r)>>1; int ans=(1<<30)-1; if(x<=mid)ans&=query(p<<1,l,mid,x,y); if(mid<y)ans&=query(p<<1|1,mid+1,r,x,y); return ans; } } }st; map<int,int>last; void solve() { int n; cin>>n; for(int i=1;i<=n;i++)cin>>a[i]; st.build(1,1,n); for(int i=1;i<=n;i++) { // cout<<i<<":\n"; pst.root[i]=pst.root[i-1]; if(last.count(a[i])) pst.update(pst.root[i],pst.root[i],1,n,last[a[i]],-1); last[a[i]]=i; pst.update(pst.root[i],pst.root[i],1,n,last[a[i]],1); int cur=a[i]; while(true) { int l=0,r=i,res=0; while(l<r) { int mid=(l+r+1)>>1; int now=st.query(1,1,n,mid,i); if(now<cur)l=mid,res=mid; else r=mid-1; } if(!res)break; cur=st.query(1,1,n,res,i); // cout<<cur<<' '<<l<<' '<<i<<'\n'; if(last.count(cur)) pst.update(pst.root[i],pst.root[i],1,n,last[cur],-1); last[cur]=res; pst.update(pst.root[i],pst.root[i],1,n,last[cur],1); } // cout<<'\n'; } int q; cin>>q; int lastans=0; while(q--) { int l,r; cin>>l>>r; l=(l^lastans)%n+1; r=(r^lastans)%n+1; if(l>r)swap(l,r); cout<<(lastans=pst.query(pst.root[r],1,n,l,n))<<'\n'; } } /* */ #undef int int main() { ios::sync_with_stdio(false);cin.tie(nullptr); // cout<<fixed<<setprecision(15); // int _;cin>>_;while(_--) { solve(); } return 0; }
__EOF__

本文作者:Jerry-Black
本文链接:https://www.cnblogs.com/Jerry-Black/p/17372473.html
关于博主:小蒟蒻一只( ̄^ ̄)ゞ
版权声明:转载请注明来源哟~ QAQ
声援博主:UP UP UP !!!
本文链接:https://www.cnblogs.com/Jerry-Black/p/17372473.html
关于博主:小蒟蒻一只( ̄^ ̄)ゞ
版权声明:转载请注明来源哟~ QAQ
声援博主:UP UP UP !!!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)