Luogu8078

前言

快写害死人!(场上我快写写挂,痛失 100pts

没想到回滚莫队 + 链表等神仙做法,于是憨憨地打了一个压位 Trie+ 普通莫队。

前置芝士

解法

你发现暴力莫队 O(nnlogn) 很悬。

你考虑优化它。

你发现它要支持插入、删除、前驱、后继操作,即 Dynamic Predecessor Problem

平衡树于是可以换成压位 Trie。

然后跑得还蛮快?

复杂度 O(nnlogwn),(应该)可以通过。

提供一组极限数据

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;
}
posted @   myee  阅读(46)  评论(0编辑  收藏  举报
编辑推荐:
· 从 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)
点击右上角即可分享
微信分享提示