题目都太难了 我心态有点爆炸 来点简单的东西愉悦一下身心。
打代码真的是一件令人欢快的事情。
KD-tree这个数据结构以前学过好多遍了 以前我还学会过 但是好像一直没写过到现在也就忘了。。
趁这个晚上赶紧补一发。
首先是 nth_element函数 所需头文件 algorithm
使用格式nth_element(begin,nth,end,compare); 显然和sort一致都是左闭右开的。
假设1~m有值 现在要求第n大 那么这样写nth_element(a+1,a+n,a+m+1,cmp);
其作用为把第n大的数字放在相应的位置 值得一提的是这个时候所有比n大的数字都在n后面比n小的数字在n的前面。
原因是 这个函数拥有sort的一部分 快排。这样就很方便的使整个数组近乎有序了。
注意 其并不返回值我们需要再调用一下数组才行。
查了一会的错 发现 min打成max了 l打成1了。。
模板题:[luogu4184简单题](https://www.luogu.com.cn/problem/P4148)
这道题强制在线了 所以CDQ分治解决不了了(我也很久没写过CDQ分治了。最近的还是分治FFT的时候写的 但是那不算吧。
所以我们采用2-D tree来解决问题由于动态插入显然我们采用替罪羊树做平衡树即可。
复杂度有保证这样KD-tree的复杂度为\(n\sqrt{n}\) 注意重构参数调节 不需要什么剪枝。。
这道题目是一个求某个点的第k远点问题 我们考虑KD-tree+堆来实现。
然后暴力搜索 注意加上离其最近矩阵距离的剪枝即可。
复杂度 O(玄学)
这道题显然是一个四维偏序问题。好像排序+CDQ+CDQ+树状数组可以搞。
但是我不太会写这个东西好久没写偏序问题了。考虑排序之后剩下了一个三维偏序。
我们使用3-D tree解决这个问题 显然树的深度为Klogn 我们计算出来某个点的值然后暴力更新树上的点 总复杂度nKlogn
然后查询时复杂度为 3-D tree标准复杂度 所以总复杂度为\(nKlogn+n^{\frac{5}{3}}\)
显然可以通过这道题。
再有就是一些KD-tre维护一些偏序问题什么的 都比较简单。
但是注意要会写 剪枝要加对 还有就是重构的时候不要犹豫 复杂度正确的。
这道题 求某个区间中只出现一次的数字的最大值。不能莫队。。
也不带修改(带修就非常的麻烦了。。 考虑 转换成 某个数字前驱在 0-l-1 后继 在r+1~n+1 其本身在l~r内对答案的贡献。
可以发现这个是一个简单的三维偏序问题我们直接上3D树解决即可。
但是这并非重点 我们其实可以考虑 树套树套树解决 发现对空间和时间消耗过大。
考虑优化我们对前驱开可持久化 解决一维 建立可持久化的nex值域主席树 又解决一维 考虑主席树下再吊一颗线段树成功解决三维。
发现空间时间 都是nlog^2n的 可以通过此题。这好像是我第二次写主席树套线段树 所以代码放出来 但bzoj CE了不知道为什么。
//#include<bits\stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 1000000000
#define ld long double
#define pb push_back
#define put(x) printf("%d\n",x)
#define min(x,y) ((x)>(y)?(y):(x))
#define max(x,y) ((x)>(y)?(x):(y))
#define rep(p,n,i) for(ll i=p;i<=n;++i)
#define x(p) t[p].x
#define las(p) t[p].las
#define ne(p) t[p].ne
#define ps(x) t[x].ps
#define l(x) s[x].l
#define r(x) s[x].r
#define rt(x) s[x].rt
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
const int MAXN=100010;
int n,m,cnt,tot;
int root[MAXN];
int vis[MAXN],ans;
struct wy
{
int x,las,ne,ps;
int friend operator <(wy a,wy b){return a.las==b.las?a.ps<b.ps:a.las<b.las;}
}t[MAXN];
struct jl{int l,r;int rt;}s[MAXN*30];//外层主席树
struct ysn{int l,r;int mx;}w[MAXN*220];//内层线段树
inline void ins(int &p,int o,int l,int r,int x,int v)
{
p=++tot;w[p]=w[o];
w[p].mx=max(w[p].mx,v);
if(l==r)return;
int mid=(l+r)>>1;
if(x<=mid)ins(w[p].l,w[o].l,l,mid,x,v);
else ins(w[p].r,w[o].r,mid+1,r,x,v);
}
inline void insert(int &p,int o,int l,int r,int x,int v,int vv)
{
p=++cnt;s[p]=s[o];
ins(rt(p),rt(o),1,n,v,vv);
if(l==r)return;
int mid=(l+r)>>1;
if(x<=mid)insert(l(p),l(o),l,mid,x,v,vv);
else insert(r(p),r(o),mid+1,r,x,v,vv);
}
inline void ask(int p,int l,int r,int L,int R)
{
if(!p)return;
if(l==L&&R==r){ans=max(ans,w[p].mx);return;}
int mid=(l+r)>>1;
if(R<=mid){ask(w[p].l,l,mid,L,R);return;}
if(L>mid){ask(w[p].r,mid+1,r,L,R);return;}
ask(w[p].l,l,mid,L,mid);ask(w[p].r,mid+1,r,mid+1,R);
}
inline void ask(int p,int l,int r,int L,int R,int LL,int RR)
{
if(!p)return;
if(L<=l&&R>=r)
{
ask(rt(p),1,n,LL,RR);
return;
}
int mid=(l+r)>>1;
if(L<=mid)ask(l(p),l,mid,L,R,LL,RR);
if(R>mid)ask(r(p),mid+1,r,L,R,LL,RR);
}
int main()
{
freopen("1.in","r",stdin);
n=read();m=read();
for(int i=1;i<=n;++i)
{
x(i)=read();
las(i)=vis[x(i)];
ps(i)=i;vis[x(i)]=i;
}
memset(vis,0,sizeof(vis));
for(int i=n;i>=1;--i)
{
ne(i)=vis[x(i)]==0?n+1:vis[x(i)];
vis[x(i)]=i;
}
sort(t+1,t+1+n);
int flag=1;
for(int i=0;i<=n;++i)
{
if(i)root[i]=root[i-1];
while(flag<=n&&t[flag].las==i)
{
insert(root[i],root[i],1,n+1,ne(flag),ps(flag),x(flag));
++flag;
}
}
for(int i=1;i<=m;++i)
{
int l=read(),r=read();
l=(l+ans)%n+1;
r=(r+ans)%n+1;
if(l>r)swap(l,r);
ans=0;ask(root[l-1],1,n+1,r+1,n+1,l,r);
printf("%d\n",ans);
}
return 0;
}