您的位置:首页 > 其它

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。

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: