URAL 1977 Energy Wall(成段更新)
来源:互联网 发布:人工智能豆瓣评分 编辑:程序博客网 时间:2024/05/17 03:17
题意:有N(N<10^9)个点,P(P<10^5)个操作,每一秒过后,所以的数都会加上一个值T,每个操作前都有操作的时间,初始的时间是0,操作有两种类型,(1)"save l r",表示求区间[L,R]之间的所以数的和,并加到tot里,然后把[L,R]清空为零,(2)"enforce i d",表示点i-d+1和点i+d-1加上值X,点i-d+2和点i+d-2加上值2*X……并且,最后所有数加上的X的和等于tot,这个操作之后,tot清零。
可知,操作(2)的话,可以看成加上两个等差数列,一个递增一个递减,对于每过一段时间就会所有数就会增加值,也可以表示成加上等差数列。需要注意的时,因为点的数目为10^9,所以要对操作的点离散化,比如有10个点,离散化之后有1、2、7、10。当操作的区间是[2,7]时,中间还有3,4,5,6,这几个数,所以在线段树的每个区间都要加一个值,表示将区间分割之后,中间的数的值和(比如1、2、7、10,分割成区间[1,2]和[7,10],增加一个变量extra表示中间3、4、5、6。
#include <iostream>#include <cstdio>#include <cstring>#include <vector>#include <algorithm>#include <map>using namespace std;typedef long long LL;#define LL(x) (x<<1)#define RR(x) (x<<1|1)#define MID(a,b) (a+((b-a)>>1))const int N=4e5+5;int n,m,p;bool type[N/4];int idx[N/4],K1[N/4],K2[N/4];bool flag[N*4];double l_add[N*4],r_add[N*4],extra[N*4];double delta[N*4],sum[N*4];vector<int> SY;map<int,int> H;struct Segtree{ double calc(int mid,double add,double valu) { int len=(SY[mid+1]-SY[mid])-1; if(len>0) { double add1=add+valu; double add2=add+(len)*valu; return (add1+add2)*len/2; } return 0; } void fun_add(double add1,double add2,double valu,int len,int ind) { sum[ind]+=(add1+add2)*len/2; l_add[ind]+=add1; r_add[ind]+=add2; delta[ind]+=valu; } void fun_zero(int ind) { sum[ind]=extra[ind]=0; flag[ind]=1; l_add[ind]=r_add[ind]=delta[ind]=0; } void PushDown(int lft,int rht,int ind) { int mid=MID(lft,rht); if(flag[ind]) { fun_zero(LL(ind)); fun_zero(RR(ind)); flag[ind]=0; } if(l_add[ind]||r_add[ind]) { double tmp1=l_add[ind]+(SY[mid]-SY[lft])*delta[ind]; double tmp2=tmp1+(SY[mid+1]-SY[mid])*delta[ind]; int len1=SY[mid]-SY[lft]+1; int len2=SY[rht]-SY[mid+1]+1; fun_add(l_add[ind],tmp1,delta[ind],len1,LL(ind)); fun_add(tmp2,r_add[ind],delta[ind],len2,RR(ind)); extra[ind]+=calc(mid,tmp1,delta[ind]); l_add[ind]=r_add[ind]=delta[ind]=0; } } void PushUp(int ind) { sum[ind]=sum[LL(ind)]+sum[RR(ind)]+extra[ind]; } void build(int lft,int rht,int ind) { flag[ind]=0; l_add[ind]=r_add[ind]=extra[ind]=0; delta[ind]=sum[ind]=0; if(lft!=rht) { int mid=MID(lft,rht); build(lft,mid,LL(ind)); build(mid+1,rht,RR(ind)); } } void updata(int st,int ed,double add1,double add2,double valu,int lft,int rht,int ind) { if(st<=lft&&rht<=ed) fun_add(add1,add2,valu,SY[rht]-SY[lft]+1,ind); else { int mid=MID(lft,rht); PushDown(lft,rht,ind); if(ed<=mid) updata(st,ed,add1,add2,valu,lft,mid,LL(ind)); else if(st>mid) updata(st,ed,add1,add2,valu,mid+1,rht,RR(ind)); else { double tmp1=add1+(SY[mid]-SY[st])*valu; double tmp2=tmp1+(SY[mid+1]-SY[mid])*valu; updata(st,mid,add1,tmp1,valu,lft,mid,LL(ind)); updata(mid+1,ed,tmp2,add2,valu,mid+1,rht,RR(ind)); extra[ind]+=calc(mid,tmp1,valu); } PushUp(ind); } } void setZero(int st,int ed,int lft,int rht,int ind) { if(st<=lft&&rht<=ed) { //cout<<"setZero: lft="<<lft<<" rht="<<rht<<endl; fun_zero(ind); } else { int mid=MID(lft,rht); PushDown(lft,rht,ind); if(ed<=mid) setZero(st,ed,lft,mid,LL(ind)); else if(st>mid) setZero(st,ed,mid+1,rht,RR(ind)); else { extra[ind]=0; setZero(st,ed,lft,mid,LL(ind)); setZero(st,ed,mid+1,rht,RR(ind)); } PushUp(ind); } } double query(int st,int ed,int lft,int rht,int ind) { if(st<=lft&&rht<=ed) { return sum[ind]; } else { int mid=MID(lft,rht); PushDown(lft,rht,ind); double ans; if(ed<=mid) ans=query(st,ed,lft,mid,LL(ind)); else if(st>mid) ans=query(st,ed,mid+1,rht,RR(ind)); else { double sum1=query(st,ed,lft,mid,LL(ind)); double sum2=query(st,ed,mid+1,rht,RR(ind)); ans=sum1+sum2+extra[ind]; } PushUp(ind); return ans; } }}seg;int main(){ //freopen("in.txt","r",stdin); while(scanf("%d%d%d",&n,&p,&m)!=EOF) { SY.clear(); H.clear(); for(int i=0;i<m;i++) { char op[10]; scanf("%d%s%d%d",&idx[i],op,&K1[i],&K2[i]); if(op[0]=='s') { type[i]=0; SY.push_back(K1[i]); SY.push_back(K2[i]); } else { type[i]=1; SY.push_back(K1[i]+K2[i]-1); SY.push_back(K1[i]-K2[i]+1); SY.push_back(K1[i]); SY.push_back(K1[i]+1); } } sort(SY.begin(),SY.end()); SY.erase(unique(SY.begin(),SY.end()),SY.end()); int len=(int)SY.size(); for(int i=0;i<len;i++) H[SY[i]]=i; //for(int i=0;i<len;i++) cout<<SY[i]<<" ";cout<<endl; double tot=0; int pre=0; seg.build(0,len-1,1); for(int i=0;i<m;i++) { double tmp=(idx[i]-pre)*1.0*p; seg.updata(0,len-1,tmp,tmp,0,0,len-1,1); pre=idx[i]; if(type[i]==0) { int st=H[K1[i]],ed=H[K2[i]]; tot+=seg.query(st,ed,0,len-1,1); //printf("check: %.6f\n",seg.query(st,ed,0,len-1,1)); seg.setZero(st,ed,0,len-1,1); printf("%.10f\n",tot); } else { int st1=H[ K1[i]-K2[i]+1 ]; int ed1=H[ K1[i] ]; int st2=H[ K1[i]+1 ]; int ed2=H[ K1[i]+K2[i]-1 ]; double delta=tot/((LL)K2[i]*K2[i]); if(tot==0) continue; double tmp=delta*K2[i]; seg.updata(st1,ed1,delta,tmp,delta,0,len-1,1); if(K2[i]!=1) seg.updata(st2,ed2,tmp-delta,delta,-delta,0,len-1,1); tot=0; } } } return 0;}
- URAL 1977 Energy Wall(成段更新)
- Ural 1019 A Line painting(线段树,成段更新离散化)
- POJ 3468(成段更新)
- POJ 2991 Crane(成段更新)
- 线段树 (成段更新)
- poj2777 Count Color(成段更新)
- 綫段樹練習-成段更新
- 线段树 区间更新(成段更新) HDU1698
- 线段树几题 --------- 成段更新
- 线段树 成段更新
- 线段树 成段更新
- 线段树 成段更新
- Energy
- 线段树详解(单点更新与成段更新\区间更新操作)
- hdu 1698 Just a Hook(成段更新)
- hdu 1698 Just a Hook(成段更新)
- POJ 3667 Hotel(成段更新,区间合并)
- hdu 2871 Memory Control(成段更新,区间合并)
- [综合面试] 计算机面试书籍与求职网站推荐
- 数据结构与算法系列-队列-循环队列
- lightoj 1034 贪心 拓扑排序
- wp7使用Cocos2d-X for XNA制作一个塔防类游戏 (一)游戏基础场景搭建
- ogre 源码 一 page相关
- URAL 1977 Energy Wall(成段更新)
- 移形幻影,把不同的两个文件,合成一个文件,以达到掩饰最高境界!哈哈,好文章!!!
- 新来报道
- SVM算法
- POJ 1384 Piggy-Bank (ZOJ 2014 Piggy-Bank) 完全背包
- Learning Cocos2d-x for XNA(1)——小窥cocos2d-x框架
- LIOP特征
- 代理服务器 Squid
- 程序员的自我修养(第一章)