Luogu8078

前言

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

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

前置芝士

解法

你发现暴力莫队 \(O(n\sqrt n\log n)\) 很悬。

你考虑优化它。

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

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

然后跑得还蛮快?

复杂度 \(O(n\sqrt n\log_wn)\),(应该)可以通过。

提供一组极限数据

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 @ 2022-02-14 07:30  myee  阅读(46)  评论(0编辑  收藏  举报