P7470-[NOI Online 2021 提高组]岛屿探险【Trie,CDQ分治】

1|0正题

题目链接:https://www.luogu.com.cn/problem/P7470


1|1题目大意

给出n个二元组(a,b)

q次询问给出(l,r,c,d)表示询问[l,r]中有多少二元组满足c xor amin(b,d)

1n,q105


1|2解题思路

这个min一看就很迷,显然是让我们分两种情况讨论。

再把询问拆一下,就变成了两个条件posr/pos<lbd/b>d

两个偏序条件的话直接上CDQ,然后考虑两种情况怎么处理。

  • c xor ab:这样对于每个二元组合法的c开业被拆成Trie上最多log个区间,建Trie即可
  • c xor ad:对于每组询问在Trie上跑区间求和即可。

时间复杂度O(nlog2n)


1|3code

#include<cstdio> #include<cstring> #include<algorithm> #include<vector> using namespace std; const int N=1e5+10,M=N*24; struct node{ int w,l,id; }q[N<<1],a[N]; int n,m,tot,rt1,rt2,ans[N]; vector<node> v[N]; struct Trie1{ int cnt,ch[M][2],w[M]; void Clear(){rt1=0;cnt=0;return;} int Newp(){++cnt;ch[cnt][0]=ch[cnt][1]=w[cnt]=0;return cnt;} void Insert(int &x,int d,int l,int val){ if(!x)x=Newp(); if(d<0){w[x]++;return;} int c=(val>>d)&1; if((l>>d)&1){ Insert(ch[x][c^1],d-1,l,val); if(!ch[x][c])ch[x][c]=Newp(); w[ch[x][c]]++; } else Insert(ch[x][c],d-1,l,val); } int Ask(int x,int d,int val){ if(!x)return 0; if(d<0) return w[x]; int c=(val>>d)&1; return Ask(ch[x][c],d-1,val)+w[x]; } }T1; struct Trie2{ int cnt,ch[M][2],w[M]; void Clear(){rt2=0;cnt=0;return;} int Newp(){++cnt;ch[cnt][0]=ch[cnt][1]=w[cnt]=0;return cnt;} void Insert(int &x,int d,int val){ if(!x)x=Newp(); if(d<0){w[x]++;return;} int c=(val>>d)&1; Insert(ch[x][c],d-1,val); w[x]=w[ch[x][0]]+w[ch[x][1]]; return; } int Ask(int x,int d,int l,int val){ if(d<0)return w[x]; int c=(val>>d)&1; if((l>>d)&1) return Ask(ch[x][c^1],d-1,l,val)+w[ch[x][c]]; return Ask(ch[x][c],d-1,l,val); } }T2; bool cmp(node x,node y) {return x.l<y.l;} void CDQ(int l,int r){ if(l==r)return; int mid=(l+r)>>1; CDQ(l,mid); CDQ(mid+1,r); sort(a+l,a+mid+1,cmp); T1.Clear();T2.Clear();tot=0; for(int i=mid+1;i<=r;i++) for(int j=0;j<v[i].size();j++) q[++tot]=v[i][j]; sort(q+1,q+1+tot,cmp); for(int i=1,z=l;i<=tot;i++){ while(z<=mid&&a[z].l<=q[i].l) T1.Insert(rt1,23,a[z].l,a[z].w),z++; if(q[i].id<0)ans[-q[i].id]-=T1.Ask(rt1,23,q[i].w); else ans[q[i].id]+=T1.Ask(rt1,23,q[i].w); } for(int i=tot,z=mid;i>=1;i--){ while(z>=l&&a[z].l>q[i].l) T2.Insert(rt2,23,a[z].w),z--; if(q[i].id<0)ans[-q[i].id]-=T2.Ask(rt2,23,q[i].l,q[i].w); else ans[q[i].id]+=T2.Ask(rt2,23,q[i].l,q[i].w); } return; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d%d",&a[i].w,&a[i].l); for(int i=1;i<=m;i++){ int l,r,c,d; scanf("%d%d%d%d",&l,&r,&c,&d); v[l].push_back((node){c,d,-i}); v[r+1].push_back((node){c,d,i}); } sort(q+1,q+1+n,cmp); CDQ(1,n+1); for(int i=1;i<=m;i++) printf("%d\n",ans[i]); return 0; }

__EOF__

本文作者QuantAsk
本文链接https://www.cnblogs.com/QuantAsk/p/15214139.html
关于博主:退役OIer,GD划水选手
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   QuantAsk  阅读(49)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示