• KD-tree


    题目都太难了 我心态有点爆炸 来点简单的东西愉悦一下身心。

    打代码真的是一件令人欢快的事情。

    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的复杂度为(nsqrt{n}) 注意重构参数调节 不需要什么剪枝。。

    luogu2093
    这道题目是一个求某个点的第k远点问题 我们考虑KD-tree+堆来实现。
    然后暴力搜索 注意加上离其最近矩阵距离的剪枝即可。
    复杂度 O(玄学)

    luogu3769
    这道题显然是一个四维偏序问题。好像排序+CDQ+CDQ+树状数组可以搞。
    但是我不太会写这个东西好久没写偏序问题了。考虑排序之后剩下了一个三维偏序。
    我们使用3-D tree解决这个问题 显然树的深度为Klogn 我们计算出来某个点的值然后暴力更新树上的点 总复杂度nKlogn
    然后查询时复杂度为 3-D tree标准复杂度 所以总复杂度为(nKlogn+n^{frac{5}{3}})
    显然可以通过这道题。
    再有就是一些KD-tre维护一些偏序问题什么的 都比较简单。
    但是注意要会写 剪枝要加对 还有就是重构的时候不要犹豫 复杂度正确的。
    bzoj3948
    这道题 求某个区间中只出现一次的数字的最大值。不能莫队。。
    也不带修改(带修就非常的麻烦了。。 考虑 转换成 某个数字前驱在 0-l-1 后继 在r+1~n+1 其本身在l~r内对答案的贡献。
    可以发现这个是一个简单的三维偏序问题我们直接上3D树解决即可。
    但是这并非重点 我们其实可以考虑 树套树套树解决 发现对空间和时间消耗过大。
    考虑优化我们对前驱开可持久化 解决一维 建立可持久化的nex值域主席树 又解决一维 考虑主席树下再吊一颗线段树成功解决三维。
    发现空间时间 都是nlog^2n的 可以通过此题。这好像是我第二次写主席树套线段树 所以代码放出来 但bzoj CE了不知道为什么。

    //#include<bitsstdc++.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
    ",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
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    JAVA编程-------29、求3*3矩阵对角线元素之和
    JAVA编程---------28、对10个数进行排序(冒泡排序)
    JAVA编程-------------27、100以内的素数
    JAVA编程----------26、请输入星期几的第一个字母来判断一下星期几, 第一个字母相同,则判断第二个字母,以此类推
    JAVA编程-----------25、查找5位数的回文数
    JAVA编程---------24、输入一个数,判断位数,并逆序输出
    JAVA编程------------23、递归
    JAVA编程------------22、利用递归求5!
    JAVA编程--------21、求1!+2!+....+20!=
    JAVA编程------------20、计算2/1+3/2+5/3+8/5+...求前20项之和
  • 原文地址:https://www.cnblogs.com/chdy/p/12420174.html
Copyright © 2020-2023  润新知