【BZOJ4605】崂山白花蛇草水 权值线段树+kd-tree
【BZOJ4605】崂山白花蛇草水
Description
Input
Output
Sample Input
1 1 1 1
1 2 2 3
1 4 1 2
1 3 4 4
2 1 1 4 1 3
2 2 2 3 5 4
2 2 1 4 4 2
Sample Output
NAIVE!ORZzyz.
3
题解:本题的做法好像挺多,kd-tree套平衡树(TLE),替罪羊套kd-tree(两次重构吓人,但是快的飞起)。然而我选择的是较易实现的权值线段树+kd-tree。
用权值线段树维护排名,然后对于每个节点都开一个kd-tree,统计既在当前排名,又在区间中的数有多少。然而数据比较坑,逼着你写重构,所以需要在每个节点对应的kd-tree失去平衡性后单独对当前的kd-tree重构。这里我用了链表记录每个点的kd-tree中的所有节点的编号,具体实现不详细解释。
然而自从加了重构,构造的数据可以过了,但是随机大数据卡的飞起,于是采用了某种猥琐的手段,求不hack~
对了,在此声明一下,有时我做完题后不知道就把源代码扔哪了,写题解的时候随手粘个东西就发上来了,所以下面放的代码有可能无法AC,如果发现这种情况欢迎指出,谢谢~
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=1000000000;
const int maxn=2500010;
int n,m,L[2],R[2],D,cntl,scnt,tcnt,ecnt,ans,sroot;
struct kd
{
int v[2],sm[2],sn[2],siz,ls,rs;
kd (){}
kd (int a,int b){v[0]=sm[0]=sn[0]=a,v[1]=sm[1]=sn[1]=b,siz=1,ls=rs=0;}
};
kd t[maxn],p[100010];
int to[maxn],next[maxn],pos[100010];
struct sag
{
int rt,siz,head,ls,rs;
void add(int x) { to[++ecnt]=x,next[ecnt]=head,head=ecnt;}
}s[maxn];
int rd()
{
int ret=0; char gc=getchar();
while(gc<'0'||gc>'9') gc=getchar();
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret;
}
bool cmp(kd a,kd b)
{
return (a.v[D]==b.v[D])?(a.v[D^1]<b.v[D^1]):(a.v[D]<b.v[D]);
}
void pushup(int x,int y)
{
kd *tx=t+x,*ty=t+y;
tx->sm[0]=max(tx->sm[0],ty->sm[0]),tx->sn[0]=min(tx->sn[0],ty->sn[0]);
tx->sm[1]=max(tx->sm[1],ty->sm[1]),tx->sn[1]=min(tx->sn[1],ty->sn[1]);
tx->siz+=ty->siz;
}
int build(int l,int r,int d)
{
if(l>r) return 0;
D=d;
int mid=l+r>>1,x=pos[mid];
nth_element(p+l,p+mid,p+r+1,cmp);
kd *tx=t+x;
t[x]=p[mid],tx->ls=build(l,mid-1,d),tx->rs=build(mid+1,r,d^1);
if(tx->ls) pushup(x,tx->ls);
if(tx->rs) pushup(x,tx->rs);
return x;
}
void insert(int x,int y)
{
D=0;
while(x!=y)
{
pushup(x,y);
if(cmp(t[x],t[y]))
{
if(!t[x].rs) t[x].rs=y;
x=t[x].rs;
}
else
{
if(!t[x].ls) t[x].ls=y;
x=t[x].ls;
}
D^=1;
}
}
void count(int x)
{
kd *tx=t+x;
if(!x||tx->sm[0]<L[0]||tx->sn[0]>R[0]||tx->sm[1]<L[1]||tx->sn[1]>R[1]) return ;
if(tx->sn[0]>=L[0]&&tx->sm[0]<=R[0]&&tx->sn[1]>=L[1]&&tx->sm[1]<=R[1])
{
cntl+=tx->siz;
return ;
}
if(tx->v[0]>=L[0]&&tx->v[0]<=R[0]&&tx->v[1]>=L[1]&&tx->v[1]<=R[1]) cntl++;
count(tx->ls),count(tx->rs);
}
void updata(int l,int r,int &x,int c,int a,int b)
{
if(!x) x=++scnt;
sag *sx=s+x;
sx->siz++,t[++tcnt]=kd(a,b),sx->add(tcnt);
if(m==50000&&sx->siz==2000)
{
sx->siz=0,pos[0]=0;
for(int i=sx->head;i;i=next[i]) pos[++pos[0]]=to[i],p[pos[0]]=kd(t[to[i]].v[0],t[to[i]].v[1]);
sx->rt=build(1,pos[0],0);
}
else
{
if(!sx->rt) sx->rt=tcnt;
else insert(sx->rt,tcnt);
}
if(l==r) return ;
int mid=l+r>>1;
if(c<=mid) updata(l,mid,sx->ls,c,a,b);
else updata(mid+1,r,sx->rs,c,a,b);
}
int query(int l,int r,int x,int a)
{
if(!x) return 0;
if(l==r) return l;
sag *sx=s+x;
int mid=l+r>>1;
cntl=0,count(s[sx->rs].rt);
if(cntl>=a) return query(mid+1,r,sx->rs,a);
return query(l,mid,sx->ls,a-cntl);
}
int main()
{
n=rd(),m=rd();
int i,a,b,c;
for(i=1;i<=m;i++)
{
if(rd()==1)
{
a=rd()^ans,b=rd()^ans,c=rd()^ans;
updata(1,N,sroot,c,a,b);
}
else
{
L[0]=rd()^ans,L[1]=rd()^ans,R[0]=rd()^ans,R[1]=rd()^ans,a=rd()^ans,cntl=0;
count(s[1].rt);
if(cntl<a) printf("NAIVE!ORZzyz.\n"),ans=0;
else ans=query(1,N,sroot,a),printf("%d\n",ans);
}
}
return 0;
}
【BZOJ4605】崂山白花蛇草水 权值线段树+kd-tree的更多相关文章
- bzoj4605: 崂山白花蛇草水 权值线段树套KDtree
bzoj4605: 崂山白花蛇草水 链接 bzoj loj 思路 强制在线,那就权值线段树套KDtree好了,没啥好讲的. KDtree要加平衡因子来重构.另外,那水真难喝. 错误 树套树一边写过了, ...
- 【bzoj4605】崂山白花蛇草水 权值线段树套KD-tree
题目描述 神犇Aleph在SDOI Round2前立了一个flag:如果进了省队,就现场直播喝崂山白花蛇草水.凭借着神犇Aleph的实力,他轻松地进了山东省省队,现在便是他履行诺言的时候了.蒟蒻Bob ...
- 崂山白花蛇草水 权值线段树套KDtree
Description 神犇Aleph在SDOI Round2前立了一个flag:如果进了省队,就现场直播喝崂山白花蛇草水.凭借着神犇Aleph的实 力,他轻松地进了山东省省队,现在便是他履行诺言的时 ...
- 洛谷P4848 崂山白花蛇草水 权值线段树+KDtree
题目描述 神犇 \(Aleph\) 在 \(SDOI\ Round2\) 前立了一个 \(flag\):如果进了省队,就现场直播喝崂山白花蛇草水.凭借着神犇 \(Aleph\) 的实力,他轻松地进了山 ...
- BZOJ 4605 崂山白花蛇草水(权值线段树+KD树)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4605 [题目大意] 操作 1 x y k 表示在点(x,y)上放置k个物品, 操作 2 ...
- 【树状数组套权值线段树】bzoj1901 Zju2112 Dynamic Rankings
谁再管这玩意叫树状数组套主席树我跟谁急 明明就是树状数组的每个结点维护一棵动态开结点的权值线段树而已 好吧,其实只有一个指针,指向该结点的权值线段树的当前结点 每次查询之前,要让指针指向根结点 不同结 ...
- 【BZOJ-2892&1171】强袭作战&大sz的游戏 权值线段树+单调队列+标记永久化+DP
2892: 强袭作战 Time Limit: 50 Sec Memory Limit: 512 MBSubmit: 45 Solved: 30[Submit][Status][Discuss] D ...
- BZOJ4605 : 崂山白花蛇草水
外层维护权值线段树,内层维护kd-tree. 修改的时候只往右儿子里插入,不平衡的时候替罪羊式重构. 查询的时候在外层线段树上走,在内层kd-tree上查询矩形内点数即可. 时间复杂度$O(q\log ...
- BZOJ 3110 ZJOI 2013 K大数查询 树套树(权值线段树套区间线段树)
题目大意:有一些位置.这些位置上能够放若干个数字. 如今有两种操作. 1.在区间l到r上加入一个数字x 2.求出l到r上的第k大的数字是什么 思路:这样的题一看就是树套树,关键是怎么套,怎么写.(话说 ...
随机推荐
- Fresco使用之OOM问题记录
最近友盟上5.0以上系统报出很多OOM异常,看下日志看到facebook的时候就知道一定是Fresco使用不当导致了OOM. java.lang.OutOfMemoryError: Failed to ...
- K均值聚类(C++)
#include<math.h> #include<stdio.h> #include<stdlib.h> #include<iostream> usi ...
- 洛谷——P1690 贪婪的Copy
P1690 贪婪的Copy 题目描述 Copy从卢牛那里听说在一片叫yz的神的领域埋藏着不少宝藏,于是Copy来到了这个被划分为个区域的神地.卢牛告诉了Copy这里共有个宝藏,分别放在第Pi个(1&l ...
- Longest Valid Parentheses - LeetCode
Given a string containing just the characters '(' and ')', find the length of the longest valid (wel ...
- noip2013/day1/1/转圈游戏
总时间限制: 10000ms 单个测试点时间限制: 1000ms 内存限制: 128000kB 描述 n 个小伙伴(编号从 0 到 n-1)围坐一圈玩游戏.按照顺时针方向给 n 个位置编号,从 ...
- php中for与foreach对比
总体来说,如果数据库过几十万了,才能看出来快一点还是慢一点,如果低于10万的循环,就不用测试了.php推荐用foreach.循环数字数组时,for需要事先count($arr)计算数组长度,需要引入自 ...
- Visual Studio开启SSL的支持
前提: 请确保已经安装了IIS Express 具体操作: 1.web项目->[右键]->[使用IIS Express]转换工程的Web服务器. 2.点击web项目,按[ctrl]+[w] ...
- SQL-基础学习4--聚集函数:AVG(),COUNT(),MAX(),MIN(),SUM();聚集不同值:DISTINCT
第九课 9.1 聚集函数(对某些行运行的函数,计算并返回一个值) 我们经常需要汇总数据而不用把它们实际检索出来,为此SQL提供了专门的函数.使用这些函数,SQL查询可用于检索数据,以便分析和报表生成. ...
- 给力Mac下的思维整理软件,思维导图软件合辑
给力Mac下的思维整理软件,思维导图软件合辑 1.Mindjet MindManager for mac 10.0.211 经典的头脑风暴思维导图软件 最新破解Mindjet MindManager ...
- go--互斥锁
解读: main函数里调用了两次lockPrint方法,这个方法中的println(i, "in lock")这句话,由于是在Mutex的Lock和Unlock之间,所以在第一次调 ...