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;}