Luogu8078
前言
快写害死人!(场上我快写写挂,痛失 )
没想到回滚莫队 + 链表等神仙做法,于是憨憨地打了一个压位 Trie+ 普通莫队。
前置芝士
- 普通莫队算法
- 压位 Trie
解法
你发现暴力莫队 很悬。
你考虑优化它。
你发现它要支持插入、删除、前驱、后继操作,即 Dynamic Predecessor Problem。
平衡树于是可以换成压位 Trie。
然后跑得还蛮快?
复杂度 ,(应该)可以通过。
Code
实现了一个压位 Trie。
#include <bits/stdc++.h> using namespace std; #define ONLINE_JUDGE /* --------------- fast io --------------- */ // begin namespace Fread{ const int SIZE= 1 << 16; char buf[SIZE],*S,*T; inline char getchar(){if(S==T){T=(S=buf)+ fread(buf,1,SIZE,stdin);if(S==T)return'\n';}return *S++;} } // namespace Fread namespace Fwrite { const int SIZE= 1 << 16; char buf[SIZE],*S=buf,*T=buf+SIZE; inline void flush(){fwrite(buf,1,S-buf,stdout);S=buf;} inline void putchar(char c){*S++=c;if(S==T)flush();} struct NTR{~NTR(){flush();}}ztr; } // namespace Fwrite #ifdef ONLINE_JUDGE #define getchar Fread::getchar #define putchar Fwrite::putchar #endif #include <algorithm> #include <math.h> #include <stdio.h> #include <vector> typedef long long llt; typedef unsigned uint;typedef unsigned long long ullt; typedef bool bol;typedef char chr;typedef void voi; typedef double dbl; template<typename T>bol _max(T&a,T b){return(a<b)?a=b,true:false;} template<typename T>bol _min(T&a,T b){return(b<a)?a=b,true:false;} template<typename T>T power(T base,T index,T mod){return((index<=1)?(index?base:1):(power(base*base%mod,index>>1,mod)*power(base,index&1,mod)))%mod;} template<typename T>T lowbit(T n){return n&-n;} template<typename T>T gcd(T a,T b){return b?gcd(b,a%b):a;} template<typename T>T lcm(T a,T b){return(a!=0||b!=0)?a/gcd(a,b)*b:(T)0;} template<typename T>T exgcd(T a,T b,T&x,T&y){if(!b)return y=0,x=1,a;T ans=exgcd(b,a%b,y,x);y-=a/b*x;return ans;} const uint Dep=5,W=64,LogW=6,And=W-1,Val=16777216; ullt BUFF[Val>>LogW<<1|1]; ullt*BT=BUFF+sizeof(BUFF)/sizeof(ullt); ullt*NewMemory(uint siz){return BT-=siz;} inline uint hp(ullt v){return W-__builtin_clzll(v)-1;} inline uint lp(ullt v){return __builtin_ctzll(v);} struct Trie // 压位 Trie { ullt*Node[Dep-1]; Trie(){for(uint i=0;i+1<Dep;i++)Node[i]=NewMemory(1llu<<(LogW*i));} inline voi insert(uint v) { for(uint i=Dep-2;~i;i--) { if(Node[i][v>>LogW]>>(v&And)&1)return; Node[i][v>>LogW]|=1llu<<(v&And),v>>=LogW; } } inline voi erase(uint v) { if(!(Node[Dep-2][v>>LogW]>>(v&And)&1))return; for(uint i=Dep-2;~i;i--) { Node[i][v>>LogW]&=~(1llu<<(v&And)),v>>=LogW; if(Node[i][v])return; } } inline uint pre(uint v) { for(uint i=Dep-2;~i;i--,v>>=LogW) if(Node[i][v>>LogW]&~((-1llu)<<(v&And))) { uint p=hp(Node[i][v>>LogW]&~((-1llu)<<(v&And)))|(v>>LogW<<LogW); while(++i<=Dep-2)p=(p<<LogW)|hp(Node[i][p]); return p; } return 0; } inline uint suf(uint v) { for(uint i=Dep-2;~i;i--,v>>=LogW) if(Node[i][v>>LogW]&((-1llu)<<(v&And)<<1)) { uint p=lp(Node[i][v>>LogW]&((-1llu)<<(v&And)<<1))|(v>>LogW<<LogW); while(++i<=Dep-2)p=(p<<LogW)|lp(Node[i][p]); return p; } return 0; } }T; struct ques{uint l,r,t;}Q[500005]; uint A[500005],Back[500005]; ullt Ans[500005]; ullt ans=0; #define dist(a,b) Back[a]>Back[b]?Back[a]-Back[b]:Back[b]-Back[a] inline voi insert(uint v) { uint p=T.pre(v),s=T.suf(v); T.insert(v); if(p)ans+=dist(p,v); if(s)ans+=dist(v,s); if(p&&s)ans-=dist(p,s); } inline voi erase(uint v) { T.erase(v); uint p=T.pre(v),s=T.suf(v); if(p)ans-=dist(p,v); if(s)ans-=dist(v,s); if(p&&s)ans+=dist(p,s); } inline uint read() { uint ans=0;chr c;do c=getchar();while(c>'9'||c<'0'); do ans=ans*10+(c^'0'),c=getchar();while(c<='9'&&c>='0');return ans; } inline voi write(ullt v) { static chr c[18];uint cnt=0;do c[cnt++]=v%10+'0',v/=10;while(v); while(cnt--)putchar(c[cnt]); putchar('\n'); } int main() { // freopen("rrad_s_500000.in","r",stdin); // freopen("rrads.out","w",stdout); uint n,m;n=read(),m=read(); uint Siz=n/(sqrt(m)+1.2)*sqrt(1.5)+5; // 莫队 O(n\sqrt m\log_w n) for(uint i=0;i<n;i++)Back[A[i]=read()]=i; for(uint i=0;i<m;i++)Q[i].l=read()-1,Q[i].r=read(),Q[i].t=i; std::sort(Q,Q+m,[Siz](const ques&a,const ques&b){return a.l/Siz==b.l/Siz?((a.l/Siz)&1)?a.r>b.r:a.r<b.r:a.l<b.l;}); uint l=0,r=0; for(uint i=0;i<m;i++) { ques&qs=Q[i]; while(l>qs.l)insert(A[--l]); while(r<qs.r)insert(A[r++]); while(r>qs.r)erase(A[--r]); while(l<qs.l)erase(A[l++]); Ans[qs.t]=ans; } for(uint i=0;i<m;i++)write(Ans[i]); return 0; }
本文来自博客园,作者:myee,转载请注明原文链接:https://www.cnblogs.com/myee/p/Luogu-solution-p8078.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)