/*
参考:http://hi.baidu.com/yy17yy/blog/item/3fbaaced633cc3cb2e2e21c8.html
线段树的变形,比赛的时候一直tle和mle交替,后附tle和mle的代码
和经典的线段树区间lazy操作相比,区间传递的是经验系数,每个点对系数的反应是不一样的,所以向下传递的时机有所改变,不但在区间被剖分时要向下释放,在该区间有某个点要升级的时候也要释放,因为此时用区间的lazy值叠加的话会影响结果,所以此时要释放lazy,lazy只有在这个区间的点都没到达升级门槛时才可以叠加。优化后用c++跑出359ms,暂列hdu榜首,high~
tle的代码无疑是释放太频繁了导致延时操作没起多大作用
mle的代码是将每次的系数存入一个队列,这样就超出空间限制了
*/
#include <iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<ctime>
#include<map>
#include<queue>
#include<vector>
using namespace std;
const int N=10000;
int n,m;
int sum[12];//sum[i]从i升到i+1的门槛经验值
struct Node
{int L,R;//区间左右边界int level,exp;//本区间的最大等级和最大经验值int min_dis;//本区间存在要升级点的最小经验系数int lazy;//本区间还有多少经验系数没有释放到其子树
}tree[4*N];
inline void search_up(int t)//向上更新节点的信息
{int nl=2*t,nr=2*t+1;tree[t].exp=max(tree[nl].exp,tree[nr].exp);tree[t].level=max(tree[nl].level,tree[nr].level);tree[t].min_dis=min(tree[nl].min_dis,tree[nr].min_dis);
}
void create(int t,int L,int R)//建树
{tree[t].L=L;tree[t].R=R;tree[t].level=1;tree[t].exp=0;tree[t].min_dis=sum[1]/1;//sum[1]/1值为改变,这里/1为了突出tree[t].min_dis的意义,它不是所需经验而是所需经验系数tree[t].lazy=0;int mid=(L+R)>>1;if(L<R){create(t<<1,L,mid);create((t<<1)+1,mid+1,R);}
}
inline void down(int t)//将t的lazy值释放到其子树
{int nl=t<<1,nr=(t<<1)+1;tree[nl].exp+=tree[nl].level*tree[t].lazy;tree[nl].lazy+=tree[t].lazy;tree[nl].min_dis-=tree[t].lazy;tree[nr].exp+=tree[nr].level*tree[t].lazy;tree[nr].lazy+=tree[t].lazy;tree[nr].min_dis-=tree[t].lazy;tree[t].lazy=0;
}
void update(int t,int L,int R,int val)
{int mid=(tree[t].R+tree[t].L)>>1,nl=t<<1,nr=(t<<1)+1;if(tree[t].L==tree[t].R)//如果为叶子节点,更新其等级、经验和min_dis{tree[t].exp+=tree[t].level*val;while(tree[t].exp>=sum[tree[t].level])tree[t].level++;tree[t].min_dis=(sum[tree[t].level]-tree[t].exp)/tree[t].level+((sum[tree[t].level]-tree[t].exp)%tree[t].level!=0);return ;}if(tree[t].L==L&&tree[t].R==R){if(val>=tree[t].min_dis)//本区间有点要升级,释放区间的lazy{down(t);update(nl,tree[nl].L,tree[nl].R,val);//将本次系数下放,递归到区间没有点要升级或叶子节点为止update(nr,tree[nr].L,tree[nr].R,val);search_up(t);//向上维护t的信息}else //本区间没有要升级的点{tree[t].exp+=tree[t].level*val;tree[t].min_dis-=val;tree[t].lazy+=val;}return ;}if(tree[t].lazy)//向下松弛操作{down(t);}if(R<=mid)  update(nl,L,R,val);else if(L>mid) update(nr,L,R,val);else {  update(nl,L,mid,val);update(nr,mid+1,R,val);}search_up(t);//每次update后必有search_up,因为t的子节点更新后,t的exp,level,dis_min都有可能改变
}int query(int t,int L,int R)
{int nl=t<<1,nr=(t<<1)+1;int mid=(tree[t].R+tree[t].L)>>1,tmp;if(tree[t].L==L&&tree[t].R==R){return tree[t].exp;}if(tree[t].lazy)//向下松弛操作{down(t);}if(R<=mid)tmp=query(nl,L,R);else if(L>mid)tmp=query(nr,L,R);else {tmp=max(query(nl,L,mid),query(nr,mid+1,R));}return tmp;
}
//优化输入
inline int nextInt() {  char c;  while (c = getchar(), c < '0' || c > '9');  int r = c - '0';  while (c = getchar(), c >= '0' && c <= '9') r = r * 10 + c - '0';  return r;
}
int main()
{int L,R,Case,de,ti,temp;char op[3];Case=nextInt();for(int k=1;k<=Case;k++){n=nextInt(); de=nextInt(); ti=nextInt();sum[0]=0;for(int i=1;i<de;i++){sum[i]=nextInt();}sum[de]=1<<30;create(1,1,n);printf("Case %d:\n",k);while(ti--){scanf("%s",op);L=nextInt(); R=nextInt();if(op[0]=='Q'){printf("%d\n",query(1,L,R));}else {temp=nextInt();update(1,L,R,temp);}}puts("");}
}//********************************************************************
//tle代码
#include <iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<ctime>
#include<map>
#include<queue>
#include<vector>
using namespace std;
const int N=10009;
int n,m;
int sum[22];
struct Node
{int L,R;//区间int level,exp;int q;
}tree[N*5];
int max(int x,int y)
{return x>y?x:y;
}
void create(int t,int L,int R)
{tree[t].L=L;tree[t].R=R;tree[t].level=1;tree[t].exp=0;tree[t].q=-1;int mid=(L+R)>>1;if(L<R){create(t<<1,L,mid);create((t<<1)+1,mid+1,R);}
}void down(int t)
{if(tree[t].L==tree[t].R)return ;int nl=t<<1,nr=(t<<1)+1;int tmp=tree[t].q;tree[t].q=-1;tree[nl].exp+=tree[nl].level*tmp;if(tree[nl].q==-1)tree[nl].q=tmp;else {down(nl);tree[nl].q=tmp;}while(tree[nl].exp>=sum[tree[nl].level])tree[nl].level++;tree[nr].exp+=tree[nr].level*tmp;if(tree[nr].q==-1)tree[nr].q=tmp;else{down(nr);tree[nr].q=tmp;}while(tree[nr].exp>=sum[tree[nr].level])tree[nr].level++;tree[t].exp=max(tree[2*t].exp,tree[2*t+1].exp);tree[t].level=max(tree[2*t].level,tree[2*t+1].level);
}
int update(int t,int L,int R,int val)
{int mid=(tree[t].R+tree[t].L)>>1,tmp;if(tree[t].L==L&&tree[t].R==R){if(tree[t].q==-1)tree[t].q=val;else {down(t);tree[t].q=val;}tree[t].exp+=tree[t].level*val;while(tree[t].exp>=sum[tree[t].level])tree[t].level++;return tree[t].exp;}if(tree[t].q!=-1)//向下松弛操作{down(t);}if(R<=mid)tmp=update(t<<1,L,R,val);else if(L>mid)tmp=update((t<<1)+1,L,R,val);else {tmp=max(update(t<<1,L,mid,val),update((t<<1)+1,mid+1,R,val));}tree[t].exp=max(tmp,tree[t].exp);tree[t].level=max(tree[2*t].level,tree[2*t+1].level);return tree[t].exp;
}int query(int t,int L,int R)
{int mid=(tree[t].R+tree[t].L)>>1,tmp;if(tree[t].L==L&&tree[t].R==R){return tree[t].exp;}if(tree[t].q!=-1)//向下松弛操作{down(t);}if(R<=mid)tmp=query(t<<1,L,R);else if(L>mid)tmp=query((t<<1)+1,L,R);else {tmp=max(query(t<<1,L,mid),query((t<<1)+1,mid+1,R));}return tmp;
}
int nextInt() {  char c;  while (c = getchar(), c < '0' || c > '9');  int r = c - '0';  while (c = getchar(), c >= '0' && c <= '9') r = r * 10 + c - '0';  return r;
}
int main()
{int L,R,Case,de,ti,temp;char op[2];//scanf("%d",&Case);Case=nextInt();for(int k=1;k<=Case;k++){//scanf("%d%d%d",&n,&de,&ti);n=nextInt();de=nextInt();ti=nextInt();create(1,1,n);sum[0]=0;for(int i=1;i<de;i++){//scanf("%d",&sum[i]);//sum[i]=sum[i-1]+temp;sum[i]=nextInt();}sum[de]=1<<30;printf("Case %d:\n",k);while(ti--){scanf("%s",op);if(op[0]=='Q'){//scanf("%d%d",&L,&R);//cout<<query(1,L,R)<<endl;L=nextInt();R=nextInt();printf("%d\n",query(1,L,R));}else {//scanf("%d%d%d",&L,&R,&temp);L=nextInt();R=nextInt();temp=nextInt();update(1,L,R,temp);}}printf("\n");}
}//*******************************************************************************
//mle代码
#include <iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<ctime>
#include<map>
#include<queue>
#include<vector>
using namespace std;
const int N=10009;
int n,m;
int sum[12];
struct Node
{int L,R;//区间int level,exp;queue<int> q;
}*tree;
void create(int t,int L,int R)
{tree[t].L=L;tree[t].R=R;tree[t].level=1;tree[t].exp=0;int mid=(L+R)>>1;if(L<R){create(t<<1,L,mid);create((t<<1)+1,mid+1,R);}
}void down(int t)//将t释放至其子树
{if(tree[t].L==tree[t].R)return ;int nl=t<<1,nr=(t<<1)+1;while(!tree[t].q.empty()){int tmp=tree[t].q.front();tree[t].q.pop();tree[nl].exp+=tree[nl].level*tmp;tree[nl].q.push(tmp);while(tree[nl].exp>=sum[tree[nl].level])tree[nl].level++;tree[nr].exp+=tree[nr].level*tmp;tree[nr].q.push(tmp);while(tree[nr].exp>=sum[tree[nr].level])tree[nr].level++;}
}
int update(int t,int L,int R,int val)
{int mid=(tree[t].R+tree[t].L)>>1,tmp;if(tree[t].L==L&&tree[t].R==R){tree[t].q.push(val);tree[t].exp+=tree[t].level*val;while(tree[t].exp>=sum[tree[t].level])tree[t].level++;return tree[t].exp;}if(!tree[t].q.empty())//向下松弛操作{down(t);}if(R<=mid)tmp=update(t<<1,L,R,val);else if(L>mid)tmp=update((t<<1)+1,L,R,val);else {tmp=max(update(t<<1,L,mid,val),update((t<<1)+1,mid+1,R,val));}tree[t].exp=max(tmp,tree[t].exp);tree[t].level=max(tree[t].level,max(tree[2*t].level,tree[2*t+1].level));return tmp;
}int query(int t,int L,int R)
{int mid=(tree[t].R+tree[t].L)>>1,tmp;if(tree[t].L==L&&tree[t].R==R){return tree[t].exp;}if(!tree[t].q.empty())//向下松弛操作{down(t);}if(R<=mid)tmp=query(t<<1,L,R);else if(L>mid)tmp=query((t<<1)+1,L,R);else {tmp=max(query(t<<1,L,mid),query((t<<1)+1,mid+1,R));}return tmp;
}int nextInt() {  char c;  while (c = getchar(), c < '0' || c > '9');  int r = c - '0';  while (c = getchar(), c >= '0' && c <= '9') r = r * 10 + c - '0';  return r;
}
int main()
{int L,R,Case,de,ti,temp;char op[2];//scanf("%d",&Case);Case=nextInt();for(int k=1;k<=Case;k++){//scanf("%d%d%d",&n,&de,&ti);n=nextInt();de=nextInt();ti=nextInt();tree=new Node[4*n];create(1,1,n);sum[0]=0;for(int i=1;i<de;i++){sum[i]=nextInt();}sum[de]=1<<30;printf("Case %d:\n",k);while(ti--){scanf("%s",op);if(op[0]=='Q'){//scanf("%d%d",&L,&R);//cout<<query(1,L,R)<<endl;L=nextInt();R=nextInt();printf("%d\n",query(1,L,R));}else {//scanf("%d%d%d",&L,&R,&temp);L=nextInt();R=nextInt();temp=nextInt();update(1,L,R,temp);}}printf("\n");delete tree;}
}

												

HDU 3954 Level up 2011 Alibaba Programming Contest 线段树相关推荐

  1. HDU 3954 Level up(线段树)

    HDU 3954 Level up 题目链接 题意:k个等级,n个英雄,每一个等级升级有一定经验,每次两种操作,一个区间加上val,这样区间内英雄都获得当前等级*val的经验,还有一个操作询问区间经验 ...

  2. HDU - 5381 The sum of gcd(莫队/线段树区间合并)

    题目链接:点击查看 题目大意:给出一个长度为 nnn 的序列,再给出 mmm 次询问,每次询问需要回答区间 [L,R][L,R][L,R] 内所有子区间的 gcdgcdgcd 之和.更具体的,对于询问 ...

  3. HDU 6155 Subsequence Count (DP、线性代数、线段树)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=6155 题解 DP+线代好题.(考场上过多时间刚前两题,没怎么想这题--) 首先列出一个DP式: 设\( ...

  4. hdu 1754/zstu 3121 I Hate It(线段树)

    http://acm.hdu.edu.cn/showproblem.php?pid=1754 http://acm.zstu.edu.cn:8080/JudgeOnline/showproblem?p ...

  5. HDU 6681 Rikka with Cake (可持久化线段树)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=6681 题意:一个n*m的矩形蛋糕,每次给一个点(x, y)和方向dir确定一条切的线,问最后把蛋糕分成了几 ...

  6. 【HDU 1542】Atlantis 矩形面积并(线段树,扫描法)

    [题目] Atlantis Problem Description There are several ancient Greek texts that contain descriptions of ...

  7. HDU - 6203 ping ping ping(LCA+dfs序+线段树)

    题目链接:点击查看 题目大意:给出一棵由n+1个节点组成的数,节点编号为0~n(这个无关紧要,预处理时所有节点以及n都自增1即可转换为正常的模型了),现在给出m组节点u和v,问若想让m组u和v都断开连 ...

  8. HDU 3974 Assign the task(dfs时间戳+线段树成段更新)

    题意:给定点的上下级关系,规定假设给i分配任务a.那么他的全部下属.都停下手上的工作,開始做a. 操作 T x y 分配x任务y,C x询问x的当前任务: Sample Input 1 5 4 3 3 ...

  9. HDU - 6183 Color it 2017广西邀请赛(线段树)

    题目链接 题意: 有四种操作 0操作 清空所有点 1操作 在(x,y)处插入一个带颜色的点 2 操作统计(1~x)(y1~y2)这个范围的不同的颜色数 3 结束 思路: 颜色数只有51个 我们可以建5 ...

  10. HDU 4027 Can you answer these queries?(线段树/区间不等更新)

    传送门 Can you answer these queries? Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65768/6576 ...

最新文章

  1. 中国科协发布20个重大科学问题和工程技术难题
  2. MAPREDUCE实践篇(1)
  3. Delphi xe7 android实现透明度可以调整的对话框
  4. SAP云平台和SAP HANA Enterprise Cloud(HEC)的区别
  5. ajax jsp模糊查询源码,Ajax动态执行模糊查询功能
  6. 查看宝塔面板账号密码命令_宝塔面板升级到最新版图文教程
  7. php cms专题,在phpcms中给专题每个不同分类设置独立模板
  8. GPT(Improving Language Understandingby Generative Pre-Training) 论文笔记
  9. 进入 App Store 打分
  10. Java的Post方式上传文件
  11. zz在Ubuntu中通过源码安装编译安装软件(MySQL篇)
  12. ZeroC Ice介绍与简单demo构建
  13. html如何让英文自动换行,HTML如何让英文自动换行不断词
  14. 在境内服务器、虚拟主机上运行未备案域名方法,cf worker反向代理
  15. 任正非,马云,马化腾:真正顶级厉害的人,都有一个共同特点
  16. GPK游戏包安装方法
  17. “云+移动互联时代,2014移动平台高峰论坛”隆重举行
  18. bucket name does not follow Amazon S3 standards
  19. linux skyeye,在Ubuntu 10.04上安装SkyEye及测试
  20. Opencv使用imread函数时,读到的数据为空

热门文章

  1. [Xilinx ZYNQ] #4 Petalinux 入门 [黑金资料 基础教程s1 整理]
  2. python实现排列组合
  3. 五笔字典86版wubi拆字图编码查询
  4. 使用nginx反向代理配置动态域名
  5. 百度AI车牌识别测试
  6. VB编程:取整函数Int、CInt、Fix区别-30
  7. Centos7 Samba Win10配置解决问题【全攻略】:你没有权限访问,请与管理员联系。。。
  8. The current process just got forked. Disabling parallelism to avoid deadlocks.To disable this warnin
  9. Unity Shader 之 环境光
  10. 什么镜头最适合拍风景_外出旅游,用什么镜头拍风光照比较好?