URAL 1977 Energy Wall(成段更新)
2013-11-10 22:28
246 查看
题意:有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。
可知,操作(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 1019 A Line painting(线段树,成段更新离散化)
- ural 1056. Computer Net 树的重心
- ural 1907 Coffee and Buns
- HDU 1698 Just a Hook(成段更新)
- URAL 1098 Questions 约瑟夫环
- Ural 1068 - Sum
- ural - 1470 - UFOs(树状数组)
- URAL1410. Crack
- URAL:1049 Brave Balloonists
- URAL 1117. Hierarchy
- Ural 1557 Network Attack
- ural 1020 Rope
- ural 1723 Sandro's Book
- poj 3468 线段树--成段更新
- HDU-3225 Help with Intervals 线段树成段更新
- URAL 1146 Maximum Sum & HDU 1081 To The Max (DP)
- Ural - Timus - 1009 K-based Numbers 题解
- ural1057 Amount of Degrees
- [BZOJ1977][Beijing2010组队][LCA][Kruskal]次小生成树
- URAL 1837 Isenbaev's Number