Description

 小C正在出一道题...因为语文水平有限他想不出复杂的背景,所以以下就是题意了。
  平面上有N个点,开始时每个点属于一个不同的集合。不妨设点Pi属于集合Si。请维护数据结构支持以下三种操作:
  "Merge x y":将集合Sy中的点到Sx中;
  "Split i d v"(d ∈ {0, 1}):创建新集合Sc + 1,Sc + 2,之后将集合Si中的所有点中,第d维坐标不超过v的到集合Sc + 1中,超过v的移动到集合Sc + 2中,其中c为现有集合数( 包括之前合并和分割中产生的空集 );
  "Query i":查询集合Si中点权值的最大值,最小值及和;
  "Add i d":将集合Si中所有点的权值增加d。
  方便起见,对于d ∈ {0, 1},输入的所有点的第d维坐标不重复。所有操作涉及的集合非空。

Input

  第一行一个整数N表示点数。
  接下来N行,每行3个整数分别表示Pi的坐标与权值。
  接下来一个整数Q表示操作数。
  接下来Q行,每行描述一个操作,格式如上所述。

Output

  对于每个Q操作,输出三个整数,依次表示询问集合权值的最大值,最小值与和。
预处理出点集的一颗二维k-d tree
将每个点到根的路径复制出来作为初始状态
由于树形态相同,合并和分裂可以仿照线段树
分裂时增加的点数$T(n)=2T(\frac{n}{4})+O(1)=O(\sqrt{n})$
合并复杂度与减少的点数同阶
因此总时间复杂度$O(q\sqrt{n})$
由每个点到根的路径长度之和可得空间复杂度的上界$O(nlogn)$
#include<bits/stdc++.h>
#define G getchar()
int _(){
int x=,f=,c=G;
while(c<)c=='-'&&(f=-),c=G;
while(c>)x=x*+c-,c=G;
return x*f;
}
int _s(){
int c=G,c0;
while(c<)c=G;
c0=c;
while(c>)c=G;
return c0;
}
int min(int a,int b){return a<b?a:b;}
int max(int a,int b){return a>b?a:b;}
const int N=,inf=0x3f3f3f3f;
int n,qp;
struct node;
node*newnode();
struct node{
node*c[];
int mn[],mx[];
int mnv,mxv,sz,id;
long long sum,a;
void add(long long x){
if(this){
a+=x;
mnv+=x;
mxv+=x;
sum+=x*sz;
}
}
void dn(){
if(a){
c[]->add(a);
c[]->add(a);
a=;
}
}
void up(){
mnv=inf;mxv=-inf;sum=;
sz=;
if(c[]){
mnv=c[]->mnv;
mxv=c[]->mxv;
sum=c[]->sum;
sz=c[]->sz;
}
if(c[]){
mnv=min(mnv,c[]->mnv);
mxv=max(mxv,c[]->mxv);
sum+=c[]->sum;
sz+=c[]->sz;
}
}
void set(int x0,int x1,int v){
mn[]=mx[]=x0;
mn[]=mx[]=x1;
sum=mnv=mxv=v;
sz=;a=;
}
void query(){
printf("%d %d %lld\n",mxv,mnv,sum);
}
void upds(){
for(int i=;i<;++i){
mn[i]=min(c[]->mn[i],c[]->mn[i]);
mx[i]=max(c[]->mx[i],c[]->mx[i]);
}
}
}mem[N*],*pool[N*],*rt0,*n0[N],*rts[N*];
int pp;
node*newnode(){
return pool[--pp];
}
int dx=;
bool cmp(node*a,node*b){
return a->mn[dx]<b->mn[dx];
}
node*build(int L,int R){
if(L==R)return n0[L];
int M=(L+R)>>;
std::nth_element(n0+L,n0+M,n0+R+,cmp);
node*w=newnode();
dx^=;
w->c[]=build(L,M);
w->c[]=build(M+,R);
w->upds();
dx^=;
return w;
}
node*ss[];
int sp=;
void init(node*w){
ss[sp++]=w;
if(w->id){
node*t=w;
for(int i=sp-;~i;--i){
node*u=newnode();
*u=*ss[i];
int d=u->c[]==ss[i+];
u->c[d]=t;
u->c[d^]=;
u->up();
t=u;
}
rts[w->id]=t;
}else{
init(w->c[]);
init(w->c[]);
}
--sp;
}
int _x,_d;
void split(node*w,node*&l,node*&r){
if(!w)l=r=;
else if(_x<w->mn[_d])l=,r=w;
else if(w->mx[_d]<=_x)l=w,r=;
else{
w->dn();
node*u=newnode();
*u=*w;
split(w->c[],w->c[],u->c[]);
split(w->c[],w->c[],u->c[]);
w->up();u->up();
l=w,r=u;
}
}
node*merge(node*a,node*b){
if(!a)return b;
if(!b)return a;
a->dn();b->dn();
a->c[]=merge(a->c[],b->c[]);
a->c[]=merge(a->c[],b->c[]);
a->up();
pool[pp++]=b;
return a;
}
int main(){
n=_();
pp=n*;
for(int i=;i<pp;++i)pool[i]=mem+i;
for(int i=,x,y;i<=n;++i){
x=_();y=_();
n0[i]=newnode();
n0[i]->set(x,y,_());
n0[i]->id=i;
}
rt0=build(,n);
init(rt0);
for(qp=_();qp;--qp){
int o=_s();
if(o=='M'){
int x=_(),y=_();
rts[x]=merge(rts[x],rts[y]);
rts[y]=;
}else if(o=='S'){
int x=_();
_d=_();_x=_();
split(rts[x],rts[n+],rts[n+]);
rts[x]=;
n+=;
}else if(o=='Q'){
rts[_()]->query();
}else{
int x=_();
rts[x]->add(_());
}
}
return ;
}

bzoj 3615: MSS的更多相关文章

  1. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  2. BZOJ 2127: happiness [最小割]

    2127: happiness Time Limit: 51 Sec  Memory Limit: 259 MBSubmit: 1815  Solved: 878[Submit][Status][Di ...

  3. BZOJ 3275: Number

    3275: Number Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 874  Solved: 371[Submit][Status][Discus ...

  4. BZOJ 2879: [Noi2012]美食节

    2879: [Noi2012]美食节 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1834  Solved: 969[Submit][Status] ...

  5. bzoj 4610 Ceiling Functi

    bzoj 4610 Ceiling Functi Description bzoj上的描述有问题 给出\(n\)个长度为\(k\)的数列,将每个数列构成一个二叉搜索树,问有多少颗形态不同的树. Inp ...

  6. 关于TCP中的MSS

    MSS 是TCP选项中最经常出现,也是最早出现的选项.MSS选项占4byte.MSS是每一个TCP报文段中数据字段的最大长度,注意:只是数据部分的字段,不包括TCP的头部.TCP在三次握手中,每一方都 ...

  7. BZOJ 题目整理

    bzoj 500题纪念 总结一发题目吧,挑几道题整理一下,(方便拖板子) 1039:每条线段与前一条线段之间的长度的比例和夹角不会因平移.旋转.放缩而改变,所以将每条轨迹改为比例和夹角的序列,复制一份 ...

  8. 【sdoi2013】森林 BZOJ 3123

    Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数.第三行包含N个非负整数 ...

  9. 【清华集训】楼房重建 BZOJ 2957

    Description 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题,我们考虑这些 ...

随机推荐

  1. git submodule临时分支;以及git reset使用

    submodule 已经建立好了一个gitlab submodule形式的repo: 在repo A下面有一个submodule B, A --> B. clone -b branch [rep ...

  2. Java如何将字符串中的敏感词替换为相等数量的星号*

    Java如何将字符串中的敏感词替换为相等数量的星号* Java如何将字符串中的敏感词替换为相等数量的星号*,这也是我工作中遇到的问题,尝试了很多种方式最后采用这一种,在这里分享一下我的解决方式,代码效 ...

  3. python 获取昨天今天明天日期

    import datetime today = datetime.date.today() yesterday = today - datetime.timedelta(days = ) tomorr ...

  4. python 判断列表字符串元素首尾字符是否相同

    def match_words(words): ctr = for word in words: and word[] == word[-]: ctr += return ctr print(matc ...

  5. Qt5编译error01

    1.Qt551x86 vs2013 1.1.“error: C2001: 常量中有换行符” 问题还原:源码:“QString str = tr("已接收 %1MB (%2MB/s) \n共% ...

  6. kafka 官方示例代码--消费者

    kafka 0.9.0添加了一套新的Java 消费者API,用以替换之前的high-level API (基于ZK) 和low-level API.新的Java消费者API目前为测试版.另外kafka ...

  7. C#MVC中@HTML中的方法

    //生成表单 @{ Html.BeginForm("Index", "Simple", FormMethod.Post, new { id = "my ...

  8. 个人知识管理系统Version1.0开发记录(10)

    物理分页 这次我们运用Mybatis拦截器来实现物理分页,后面会运用动态sql来实现,或者运用Map/CollectionUtils/StringUtils编写工具类来实现.oracle是运用的row ...

  9. 阅读和设计源码利器UML

    https://www.w3cschool.cn/uml_tutorial/ 就不做特殊说明了啊: 一 UML 1 简介 类注释: 下面的图表示的 UML 类,该图被分为四个部分. 顶端部分被用来命名 ...

  10. Dlib——C++机器学习库,有传统机器学习的,也有深度学习的

    Dlib的目标用户并没有Hyperopt-sklearn细分,它是一个基于C++语言的通用的机器学习和数据分析库.值得一提的是,虽然Dlib的确是由C++实现的,但它却提供了针对Python语言的AP ...