题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3110

第一道线段树套线段树!

第一道标记永久化!

为什么为什么写了两个半小时啊……

本想线段树套平衡树,但想不出怎么合并不同区间上的平衡树(LCT??)。

于是看了一下Zinn的TJ。原来是线段树套线段树呀。原来外层是权值内层是区间呀。原来要动态开点呀。

  这是因为区间线段树要下传标记什么的,而权值线段树在本题中都是在叶子上修改。所以这样比较方便。

然后手胡了一番pshp,pshd。RE到飞起。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=5e4,M=1e5+;
int n,m,tt1,tt2,rtt,rt[M<<],ls[M<<],rs[M<<],L,R;
struct Node{
int ls,rs;long long lazy,sum;//ll!
}a[N*+];//每个外层点上有logn个节点
void pshd2(int cr,int &l,int &r,int lb,int rb)
{
if(!l)l=++tt2;if(!r)r=++tt2;//!!
if(!a[cr].lazy)return;
int w=a[cr].lazy,mid=lb+rb>>;
a[cr].lazy=;a[l].lazy+=w;a[r].lazy+=w;
a[l].sum+=w*(mid-lb+);a[r].sum+=w*(rb-mid);
}
void pshp2(int cr)
{
a[cr].sum=a[a[cr].ls].sum+a[a[cr].rs].sum;
}
void pshp1(int &cr,int p1,int p2)
{
if(!cr)cr=++tt2;
a[cr].sum=a[p1].sum+a[p2].sum;
a[cr].lazy=a[p1].lazy+a[p2].lazy;
if(a[p1].ls||a[p2].ls)pshp1(a[cr].ls,a[p1].ls,a[p2].ls);
if(a[p1].rs||a[p2].rs)pshp1(a[cr].rs,a[p1].rs,a[p2].rs);
}
void mdfy(int l,int r,int &cr)
{
if(!cr)cr=++tt2;
if(l>=L&&r<=R){a[cr].sum+=(r-l+);a[cr].lazy++;return;}//r-l+1!!
pshd2(cr,a[cr].ls,a[cr].rs,l,r);int mid=l+r>>;
if(L<=mid)mdfy(l,mid,a[cr].ls);
if(mid<R)mdfy(mid+,r,a[cr].rs);
pshp2(cr);
}
void mdfy(int l,int r,int &cr,int p)
{
if(!cr)cr=++tt1;
if(l==r){mdfy(,n,rt[cr]);return;}
int mid=l+r>>;
if(p<=mid)mdfy(l,mid,ls[cr],p);
else mdfy(mid+,r,rs[cr],p);
pshp1(rt[cr],rt[ls[cr]],rt[rs[cr]]);
//别pshp了,标记永久化
}
int query(int l,int r,int cr)
{
// printf("l=%d r=%d L=%d R=%d a[%d].sum=%d\n",l,r,L,R,cr,a[cr].sum);
if(l>=L&&r<=R)return a[cr].sum;
pshd2(cr,a[cr].ls,a[cr].rs,l,r);int mid=l+r>>;
if(L>mid)return query(mid+,r,a[cr].rs);
if(R<=mid)return query(l,mid,a[cr].ls);
return query(l,mid,a[cr].ls)+query(mid+,r,a[cr].rs);
}
int query(int l,int r,int cr,int k)
{
if(l==r)return l;
int mid=l+r>>;
int w=query(,n,rt[rs[cr]]);
// printf("l=%d r=%d mid=%d w=%d\n",l,r,mid,w);
if(w>=k)return query(mid+,r,rs[cr],k);
else return query(l,mid,ls[cr],k-w);
}
int main()
{
scanf("%d%d",&n,&m);int op,c;
while(m--)
{
scanf("%d%d%d%d",&op,&L,&R,&c);
if(op==)
mdfy(-N,N,rtt,c);
else
printf("%d\n",query(-N,N,rtt,c));
}
return ;
}

然后又看看Zinn的TJ。原来是标记永久化呀。抄抄抄。

标记永久化就是没有pshp和pshd。在修改的时候往下走的时候就把sum改掉(因为改sum需要知道区间大小,所以需要传L,R),不往下走的时候同样打上lazy。在查询的时候把路径上的lazy累加。细节是累加的lazy需要乘上目标区间的大小,而且因为这种写法,打lazy的时候就不能加sum了。

仍旧数组大小迷茫中。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=5e4+,M=N*;//
int n,m,tt1,tt2,lm,rtt,ls[N<<],rs[N<<],rt[N<<],lss[M],rss[M];
int L,R,op[N],x[N],y[N],c[N],tp[N];
ll sum[M],lazy[M];//ll,防止计算时爆int
void add(int l,int r,int &cr,int L,int R)//传L,R
{
if(!cr)cr=++tt2;
if(l==L&&r==R){lazy[cr]++;return;}//==
sum[cr]+=R-L+;//打了lazy就不要加sum了--看query那里
int mid=l+r>>;
if(mid<L)add(mid+,r,rss[cr],L,R);
else if(mid>=R)add(l,mid,lss[cr],L,R);
else add(l,mid,lss[cr],L,mid),add(mid+,r,rss[cr],mid+,R);
}
void insert(int l,int r,int &cr,int p)
{
if(!cr)cr=++tt1;
add(,n,rt[cr],L,R);
if(l==r)return;int mid=l+r>>;
if(p<=mid)insert(l,mid,ls[cr],p);
else insert(mid+,r,rs[cr],p);
}
//int query(int l,int r,int cr,ll lz)
//{
// if(l>=L&&r<=R)return sum[cr]+lz;
// int mid=l+r>>1;int ret=0;
// if(L<=mid)ret+=query(l,mid,lss[cr],lz+lazy[cr]);
// if(mid<R)ret+=query(mid+1,r,rss[cr],lz+lazy[cr]);
// return ret;
//}
ll query(int l,int r,int cr,int L,int R)//传L,R
{
if(!cr)return ;///////
ll ret=(R-L+)*lazy[cr];//可以每次return加ret,就不用传参数
if(l==L&&r==R)return ret+sum[cr];
int mid=l+r>>;
if(L>mid)return ret+query(mid+,r,rss[cr],L,R);
if(R<=mid)return ret+query(l,mid,lss[cr],L,R);
return ret+query(l,mid,lss[cr],L,mid)+query(mid+,r,rss[cr],mid+,R);//仔细想想只加一个ret!!!
}
int query(int l,int r,int &cr,int k)
{
if(!cr)cr=++tt1;//
if(l==r)return l;
ll w=query(,n,rt[rs[cr]],L,R),mid=l+r>>;
if(w>=k)return query(mid+,r,rs[cr],k);
else return query(l,mid,ls[cr],k-w);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
{
scanf("%d%d%d%d",&op[i],&x[i],&y[i],&c[i]);
if(op[i]==)tp[++lm]=c[i];//only op==1!!!
}
sort(tp+,tp+m+);lm=unique(tp+,tp+m+)-tp-;
for(int i=;i<=m;i++)
{
L=x[i];R=y[i];
if(op[i]==)
{
int tmp=lower_bound(tp+,tp+lm+,c[i])-tp;
insert(,lm,rtt,tmp);
}
else printf("%d\n",tp[query(,lm,rtt,c[i])]);
}
return ;
}

bzoj 3110 [Zjoi2013]K大数查询——线段树套线段树(标记永久化)的更多相关文章

  1. bzoj 3110: [Zjoi2013]K大数查询 树状数组套线段树

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1384  Solved: 629[Submit][Stat ...

  2. BZOJ 3110([Zjoi2013]K大数查询-区间第k大[段修改,在线]-树状数组套函数式线段树)

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec   Memory Limit: 512 MB Submit: 418   Solved: 235 [ Submit][ ...

  3. BZOJ 3110: [Zjoi2013]K大数查询 [树套树]

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6050  Solved: 2007[Submit][Sta ...

  4. 树套树专题——bzoj 3110: [Zjoi2013] K大数查询 &amp; 3236 [Ahoi2013] 作业 题解

    [原题1] 3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 978  Solved: 476 Descri ...

  5. BZOJ 3110: [Zjoi2013]K大数查询( 树状数组套主席树 )

    BIT+(可持久化)权值线段树, 用到了BIT的差分技巧. 时间复杂度O(Nlog^2(N)) ---------------------------------------------------- ...

  6. BZOJ 3110 [Zjoi2013]K大数查询(整体二分)

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 11654  Solved: 3505[Submit][St ...

  7. [BZOJ 3110] [Zjoi2013] K大数查询 【树套树】

    题目链接: BZOJ - 3110 题目分析 这道题是一道树套树的典型题目,我们使用线段树套线段树,一层是区间线段树,一层是权值线段树.一般的思路是外层用区间线段树,内层用权值线段树,但是这样貌似会很 ...

  8. bzoj 3110 [Zjoi2013]K大数查询(树套树)

    Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置 ...

  9. BZOJ.3110.[ZJOI2013]K大数查询(整体二分 树状数组/线段树)

    题目链接 BZOJ 洛谷 整体二分求的是第K小(利用树状数组).求第K大可以转为求第\(n-K+1\)小,但是这样好像得求一个\(n\). 注意到所有数的绝对值\(\leq N\),将所有数的大小关系 ...

随机推荐

  1. BezierCode 工具使用

    概要 今天无意间看到一个视频,发现了一款绘画Bezier 图形绘制并自动生成OC代码的神器, 因此马上先记录下. 之前一直很纠结如果程序员自己去绘制图片,久那么使用bezier 自己去画吗? 答案是: ...

  2. ps photoshop

    PS-前端切图教程(切jpg图和切png图) 参考线显示和隐藏:ctrol+h alt+v+e或者打开标尺然后从点击标尺就能拖拽出来,删除也是拖到标尺附近就删除 显示.隐藏标尺:ctrol+R 显示网 ...

  3. php中heredoc使用方法

    Heredoc技术,在正规的PHP文档中和技术书籍中一般没有详细讲述,只是提到了这是一种Perl风格的字符串输出技术.但是现在的一些论坛程序,和部分文章系统,都巧妙的使用heredoc技术,来部分的实 ...

  4. thinkphp3.2.3 nginx 连接mysql 报错 new PDO 异常

    在 php.ini 里重新指定mysql.sock 路径 pdo_mysql.default_socket=/Applications/XAMPP/xamppfiles/var/mysql/mysql ...

  5. 关于spring java.lang.IllegalArgumentException: Name for argument type [java.lang.String] 的错误

    况描述: web工程在windows环境eclipse下编译部署没有问题,系统升级时需要运维从Git取相应的源码并编译部署到线上机器,部署启动正常没有错误,当访问业务的action时报错,如下. 错误 ...

  6. MQTT入门介绍

    一简述 MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的"轻量级&q ...

  7. 健壮的 Java 基准测试

    健壮的 Java 基准测试 健壮的 Java 基准测试,第 1 部分: 问题 了解 Java 代码基准测试的问题 Brent Boyer, 程序员, Elliptic Group, Inc. 简介:程 ...

  8. cycloneii LAB-wide signals

    8 available LAB-width signals - 2 clocks - 2 clock enables - 2 asynchronous clears // - 1 asynchrono ...

  9. springboot与任务(定时任务)

    描述: 项目开发中经常需要执行一些定时任务,比如需要在每天凌晨时候,分析一次前一天的日志信息.Spring为我们提供了异步执行任务调度的方式,提供TaskExecutor .TaskScheduler ...

  10. 最新MySQL5.7.3.0版本安装(图文版本)

    转自:http://www.myexception.cn/mysql/1609536.html 可以从http://dev.mysql.com/downloads/下载MySQL服务器安装软件包,我下 ...