COJ 1010 WZJ的数据结构(十) 线段树的地狱

传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=1001

WZJ的数据结构(十)
难度级别:D; 运行时间限制:3000ms; 运行空间限制:51200KB; 代码长度限制:2000000B

试题描述

请你设计一个数据结构,高效执行以下过程:

#include<iostream>
using namespace std;
const int maxn=100010;
int A[maxn];
int tp,ql,qr,v;
int _max,_min,_sum;
int main()
{
 int n,Q,tp;
 cin>>n>>Q;
 for(int i=1;i<=n;i++) cin>>A[i];
 while(Q--)
 {
  cin>>tp>>ql>>qr;
  if(tp==2)
  {
   _sum=0; _max=-1000000000; _min=1000000000;
   for(int i=ql;i<=qr;i++)
   {
    _max=max(_max,A[i]);
    _min=min(_min,A[i]);
    _sum+=A[i];
   }
   cout<<_max<<" "<<_min<<" "<<_sum<<endl;
  }
  else
  {
   cin>>v;
   for(int i=ql;i<=qr;i++)
   {
    if(!tp) A[i]=0;
    A[i]+=v;
   }
  }
 }
 return 0;
}


输入

见代码

输出

见代码

输入示例

5 5
1 2 3 4 5
2 1 3
0 1 5 2
1 2 3 3
2 1 4
2 1 5

输出示例

3 1 6
5 2 14
5 2 16

其他说明

1<=n,Q<=100000
0<=tp<=2
1<=A[i],v<=1000
1<=ql<=qr<=n

更新:指针版:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<algorithm>
  5 #include<queue>
  6 #include<cstring>
  7 #define PAU putchar(‘ ‘)
  8 #define ENT putchar(‘\n‘)
  9 #define CH for(int d=0;d<=1;d++) if(ch[d])
 10 using namespace std;
 11 const int maxn=100000+10,maxnode=200000+10,inf=-1u>>1;
 12 struct node{
 13     node*ch[2];int mi,mx,sm,add,set,siz;node(){mi=inf;mx=-inf;sm=add=0;set=inf;}
 14     void sett(int tag){mi=mx=set=tag;sm=tag*siz;add=0;return;}
 15     void addt(int tag){add+=tag;mi+=tag;mx+=tag;sm+=tag*siz;return;}
 16     void down(){
 17         if(set!=inf){CH{ch[d]->sett(set);}set=inf;}
 18         if(add){CH{ch[d]->addt(add);}add=0;}
 19         return;
 20     }
 21     void update(){
 22         mi=inf;mx=-inf;sm=0;
 23         CH{mi=min(mi,ch[d]->mi);mx=max(mx,ch[d]->mx);sm+=ch[d]->sm;}
 24         return;
 25     }
 26 }seg[maxnode],*nodecnt=seg,*root;
 27 int A[maxn],ql,qr,cv,tp;
 28 void build(node*&x,int L,int R){
 29     x=nodecnt++;
 30     if(L==R) x->mi=x->mx=x->sm=A[L];
 31     else{
 32         int M=L+R>>1;
 33         build(x->ch[0],L,M);
 34         build(x->ch[1],M+1,R);
 35         x->update();
 36     } x->siz=R-L+1;return;
 37 }
 38 void update(node*&x,int L,int R){
 39     if(ql<=L&&R<=qr){
 40         if(tp) x->addt(cv);
 41         else x->sett(cv);
 42     }
 43     else{
 44         int M=L+R>>1;
 45         x->down();
 46         if(ql<=M) update(x->ch[0],L,M);
 47         if(qr>M) update(x->ch[1],M+1,R);
 48         x->update();
 49     }
 50     return;
 51 }
 52 int _mi,_mx,_sm;
 53 void query(node*x,int L,int R){
 54     if(ql<=L&&R<=qr){
 55         _mi=min(_mi,x->mi);
 56         _mx=max(_mx,x->mx);
 57         _sm+=x->sm;
 58     }
 59     else{
 60         int M=L+R>>1;
 61         x->down();
 62         if(ql<=M) query(x->ch[0],L,M);
 63         if(qr>M) query(x->ch[1],M+1,R);
 64     } return;
 65 }
 66 inline int read(){
 67     int x=0,sig=1;char ch=getchar();
 68     while(!isdigit(ch)){if(ch==‘-‘)sig=-1;ch=getchar();}
 69     while(isdigit(ch))x=10*x+ch-‘0‘,ch=getchar();
 70     return x*sig;
 71 }
 72 inline void write(int x){
 73     if(x==0){putchar(‘0‘);return;}if(x<0)putchar(‘-‘),x=-x;
 74     int len=0,buf[15];while(x)buf[len++]=x%10,x/=10;
 75     for(int i=len-1;i>=0;i--)putchar(buf[i]+‘0‘);return;
 76 }
 77 int n,Q;
 78 void init(){
 79     n=read();Q=read();
 80     for(int i=1;i<=n;i++) A[i]=read();
 81     build(root,1,n);
 82     return;
 83 }
 84 void work(){
 85     char ch;
 86     while(Q--){
 87         tp=read();ql=read();qr=read();
 88         if(tp!=2){
 89             cv=read();
 90             update(root,1,n);
 91         }
 92         else{
 93             _mi=inf;_mx=-inf;_sm=0;
 94             query(root,1,n);
 95             write(_mx);PAU;write(_mi);PAU;write(_sm);ENT;
 96         }
 97     }
 98     return;
 99 }
100 void print(){
101     return;
102 }
103 int main(){init();work();print();return 0;}

题解:传两个lazy标:setv,addv,addv是建立在setv上的增加量,这样来一个setv就清掉addv,来一个addv就加上去,维护懒标的时候先维护setv再维护addv就好了。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<algorithm>
  5 #include<queue>
  6 #include<cstring>
  7 #define PAU putchar(‘ ‘)
  8 #define ENT putchar(‘\n‘)
  9 using namespace std;
 10 const int maxn=100000+10,maxn3=300000+10,inf=-1u>>1;
 11 int maxv[maxn3],minv[maxn3],sumv[maxn3],setv[maxn3],addv[maxn3],A[maxn];
 12 void pushup(int o,int lc,int rc){
 13     minv[o]=min(minv[lc],minv[rc]);
 14     maxv[o]=max(maxv[lc],maxv[rc]);
 15     sumv[o]=sumv[lc]+sumv[rc];
 16     return;
 17 }
 18 void pushdown(int o,int lc,int rc){
 19     if(setv[o]>=0){
 20         setv[lc]=setv[rc]=setv[o];
 21         addv[lc]=addv[rc]=0;
 22         setv[o]=-1;
 23     } if(addv[o]){
 24         addv[lc]+=addv[o];
 25         addv[rc]+=addv[o];
 26         addv[o]=0;
 27     } return;
 28 }
 29 void maintain(int o,int L,int R){
 30     int lc=o<<1,rc=lc|1;
 31     if(L<R&&setv[o]<0) pushup(o,lc,rc);
 32     if(setv[o]>=0){
 33         minv[o]=maxv[o]=setv[o];
 34         sumv[o]=(R-L+1)*setv[o];
 35     } if(addv[o]){
 36         minv[o]+=addv[o];
 37         maxv[o]+=addv[o];
 38         sumv[o]+=(R-L+1)*addv[o];
 39     } return;
 40 }
 41 int _min,_max,_sum,ql,qr,tp,cv;
 42 void update(int o,int L,int R){
 43     if(ql<=L&&R<=qr){
 44         if(tp) addv[o]+=cv;
 45         else setv[o]=cv,addv[o]=0;
 46     } else{
 47         int M=L+R>>1,lc=o<<1,rc=lc|1;
 48         pushdown(o,lc,rc);
 49         if(ql<=M) update(lc,L,M); else maintain(lc,L,M);
 50         if(qr>M) update(rc,M+1,R); else maintain(rc,M+1,R);
 51     } maintain(o,L,R);return;
 52 }
 53 void build(int o,int L,int R){
 54     if(L==R) setv[o]=A[L];
 55     else{
 56         int M=L+R>>1,lc=o<<1,rc=lc|1;
 57         build(lc,L,M);build(rc,M+1,R);
 58     } maintain(o,L,R);return;
 59 }
 60 void query(int o,int L,int R,int add){
 61     if(setv[o]>=0){
 62         int change=setv[o]+addv[o]+add;
 63         _sum+=(min(R,qr)-max(L,ql)+1)*change;
 64         _min=min(_min,change);
 65         _max=max(_max,change);
 66     } else if(ql<=L&&R<=qr){
 67         _sum+=sumv[o]+(R-L+1)*add;
 68         _min=min(_min,minv[o]+add);
 69         _max=max(_max,maxv[o]+add);
 70     } else{
 71         int M=L+R>>1,lc=o<<1,rc=lc|1;
 72         if(ql<=M) query(lc,L,M,add+addv[o]);
 73         if(M<qr) query(rc,M+1,R,add+addv[o]);
 74     } return;
 75 }
 76 inline int read(){
 77     int x=0,sig=1;char ch=getchar();
 78     while(!isdigit(ch)){if(ch==‘-‘)sig=-1;ch=getchar();}
 79     while(isdigit(ch))x=10*x+ch-‘0‘,ch=getchar();
 80     return x*=sig;
 81 }
 82 inline void write(int x){
 83     if(x==0){putchar(‘0‘);return;}if(x<0)putchar(‘-‘),x=-x;
 84     int len=0,buf[15];while(x)buf[len++]=x%10,x/=10;
 85     for(int i=len-1;i>=0;i--)putchar(buf[i]+‘0‘);return;
 86 }
 87 int n,Q;
 88 void init(){
 89     memset(setv,-1,sizeof(setv));
 90     n=read();Q=read();
 91     for(int i=1;i<=n;i++) A[i]=read();
 92     build(1,1,n);
 93     return;
 94 }
 95 void work(){
 96     while(Q--){
 97         tp=read();ql=read();qr=read();
 98         if(tp==2){//query
 99             _sum=0;_min=inf;_max=-inf;
100             query(1,1,n,0);
101             write(_max);PAU;write(_min);PAU;write(_sum);ENT;
102         } else cv=read(),update(1,1,n);
103     }
104     return;
105 }
106 void print(){
107     return;
108 }
109 int main(){init();work();print();return 0;}
时间: 2024-08-07 04:14:18

COJ 1010 WZJ的数据结构(十) 线段树的地狱的相关文章

COJ 1010 WZJ的数据结构(十) 线段树区间操作

传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=1001 WZJ的数据结构(十) 难度级别:D: 运行时间限制:3000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,高效执行以下过程: #include<iostream>using namespace std;const int maxn=100010;int A[maxn];int tp,ql,qr,v;int

《数据结构》线段树入门(二)

今天继续介绍——线段树之延迟标记 接上期<数据结构>线段树入门(一):http://www.cnblogs.com/shadowland/p/5870339.html 在上期介绍了线段树的最基本内容(线段树单点修改,区间查询),这次将介绍:区间修改,区间查询. Question: 给你N个数,有两种操作: 1:给区间[a,b]的所有数增加X 2:询问区间[a,b]的数的和. 输入描述: 第一行一个正整数n,接下来n行n个整数,再接下来一个正整数Q,每行表示操作的个数,如果第一数是1,后接3个正

《ACM/ICPC 算法训练教程》读书笔记 之 数据结构(线段树详解)

依然延续第一篇读书笔记,这一篇是基于<ACM/ICPC 算法训练教程>上关于线段树的讲解的总结和修改(这本书在线段树这里Error非常多),但是总体来说这本书关于具体算法的讲解和案例都是不错的. 线段树简介 这是一种二叉搜索树,类似于区间树,是一种描述线段的树形数据结构,也是ACMer必学的一种数据结构,主要用于查询对一段数据的处理和存储查询,对时间度的优化也是较为明显的,优化后的时间复杂为O(logN).此外,线段树还可以拓展为点树,ZWK线段树等等,与此类似的还有树状数组等等. 例如:要将

COJ 0970 WZJ的数据结构(负三十)树分治

WZJ的数据结构(负三十) 难度级别:D: 运行时间限制:1000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 给你一棵N个点的无根树,点和边上均有权值.请你设计一个数据结构,回答M次操作. 1 x v:对于树上的每一个节点y,如果将x.y在树上的距离记为d,那么将y节点的权值加上d*v. 2 x:询问节点x的权值. 输入 第一行为一个正整数N.第二行到第N行每行三个正整数ui,vi,wi.表示一条树边从ui到vi,距离为wi.第N+1行为一个正整数M.最后

COJ 0981 WZJ的数据结构(负十九)树综合

WZJ的数据结构(负十九) 难度级别:E: 运行时间限制:15000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 WZJ的数据结构中有很多都是关于树的.这让很多练习模板的同学还要找来找去很不爽,于是WZJ跟小伙伴们一块商量如何将这些题汇拢到一块去: WZJ:为了大家简单,我规定一开始是一棵有根树. LZJ:那我一定得加上换根操作喽. XJR:链信息修改,链信息增加,链信息翻倍,维护链信息的最大,最小,总和肯定很好做. CHX:子树信息修改,子树信息增加,子树

COJ 0967 WZJ的数据结构(负三十三)

WZJ的数据结构(负三十三) 难度级别:E: 运行时间限制:7000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,完成以下功能: 给定一个大小为N的整数组A,要求你回答执行N次操作.操作分两种: 操作1:每次操作给你l,r,v三个参数,求Al至Ar中值<=v的个数. 操作2:每次操作给你l,r,v三个参数,将Al至Ar所有数的值设为v. 输入 第一行为一个正整数N.第二行为N个整数Ai.接下来N行每行4个正整数t,l,r,v.若t=2表

《数据结构》线段树入门(一)

今天介绍一种非常特殊的数据结构——线段树 首先提出一个问题: 给你n个数,有两种操作: 1:给第i个数的值增加X 2:询问区间[a,b]的总和是什么? 输入描述 输入文件第一行为一个整数n,接下来是n行n个整数,表示格子中原来的整数.接下一个正整数q,再接 下来有q行,表示q个询问,第一个整数表示询问代号,询问代号1表示增加,后面的两个数x和A表示给 位置X上的数值增加A,询问代号2表示区间求和,后面两个整数表示a和b,表示要求[a,b]之间的区间和. 样例输入 4 7 6 3 5 2 1 1

【数据结构】线段树 (定义 &amp; 点修改/区间查询)

[本文描述高级数据结构线段树的定义] [并解决 点修改/区间查询 的问题] 结构与定义 线段树的基本结构 ? 由图可知,线段树的每一个节点都代表着一段区间 且同一层的节点(深度相同的节点)所表示的区间互不重叠 所有叶子节点代表的区间左边界与右边界相同(叶子节点代表单个元素) 普遍规定 如果某个非叶子节点代表的区间包含元素个数为奇数 则它的左儿子包含的元素个数比右儿子大 1 在代码部分,非叶子节点表示区间为 [l,r] 则左儿子为 [ l , (l+r)/2 ] ,右儿子为 [ (l+r)/2+1

COJ 0979 WZJ的数据结构(负二十一)

WZJ的数据结构(负二十一) 难度级别:C: 运行时间限制:5000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 请你实现一个数据结构,完成这样的功能: 给你一个N个点的图,初始状态无边. 每次加入一条双向边(u,v,w),若加入后没有构成一棵生成树,输出“Not Yet”,否则输出当前最小生成树的权值. 输入 第一行两个正整数N,M.表示有N个点M个操作.接下来M行每行三个正整数u,v,w. 输出 每次加入一条双向边(u,v,w),若加入后没有构成一棵生成