https://acm.timus.ru/problem.aspx?space=1&num=1977
这道题目疯狂在第10个点WA,真的不知道为什么了QAQ。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define N 100010
#define NN 300010
#define NNN 600010
#define NNNN 1200010
using namespace std;
const double eps=1e-6;
double p;//每次增加的能量
int be[NNN]/*表示所保存的右边界*/;
struct node
{
int lc,rc;
double sum,l1,l2;//给一个区间打上同意的d
bool l3;
}tr[NNNN];int len;
inline double n2(int k)
{
return (double)k*1.0*(k+1)/2;
}
inline void pushl1(int x,double k,int d){tr[x].sum+=d*k;tr[x].l1+=k;}
inline void pushl2(int x,double k,int d)
{
tr[x].sum+=n2(d)*k;tr[x].l2+=k;
}
inline void pushl3(int x){tr[x].l3=1;tr[x].l1=tr[x].l2=tr[x].sum=0;}
inline void pushdown(int x,int d1,int d2)
{
if(tr[x].l3==1)
{
pushl3(tr[x].lc);pushl3(tr[x].rc);
tr[x].l3=0;
}
if(fabs(tr[x].l1)>eps)
{
pushl1(tr[x].lc,tr[x].l1,d1);pushl1(tr[x].rc,tr[x].l1,d2);
tr[x].l1=0;
}
if(fabs(tr[x].l2)>eps)
{
pushl2(tr[x].lc,tr[x].l2,d1);pushl2(tr[x].rc,tr[x].l2,d2);pushl1(tr[x].rc,tr[x].l2*d1,d2);
tr[x].l2=0;
}
}
inline void updata(int x){tr[x].sum=tr[tr[x].lc].sum+tr[tr[x].rc].sum;}
inline int tong(int l,int r){return be[r]-be[l-1];}
void bt(int l,int r)
{
int x=++len;
if(l<r)
{
int mid=(l+r)>>1;
tr[x].lc=len+1;bt(l,mid);
tr[x].rc=len+1;bt(mid+1,r);
}
}
void change1(int x,int l,int r,int ll,int rr,double k1,double k2)//两个标记一起下放
{
if(rr<ll)return ;
if(l==ll && r==rr)
{
pushl1(x,k1,tong(l,r));pushl2(x,k2,tong(l,r));return ;
}
int mid=(l+r)>>1;pushdown(x,tong(l,mid),tong(mid+1,r));
if(rr<=mid)change1(tr[x].lc,l,mid,ll,rr,k1,k2);
else if(mid<ll)change1(tr[x].rc,mid+1,r,ll,rr,k1,k2);
else
{
change1(tr[x].lc,l,mid,ll,mid,k1,k2);
change1(tr[x].rc,mid+1,r,mid+1,rr,k1+tong(ll,mid)*k2,k2);
}
updata(x);
}
void change2(int x,int l,int r,int ll,int rr)
{
if(rr<ll)return ;
if(l==ll && r==rr){pushl3(x);return ;}
int mid=(l+r)>>1;pushdown(x,tong(l,mid),tong(mid+1,r));
if(rr<=mid)change2(tr[x].lc,l,mid,ll,rr);
else if(mid<ll)change2(tr[x].rc,mid+1,r,ll,rr);
else change2(tr[x].lc,l,mid,ll,mid),change2(tr[x].rc,mid+1,r,mid+1,rr);
updata(x);
}
double findans(int x,int l,int r,int ll,int rr)//找到这个区间的和
{
if(l==ll && r==rr)return tr[x].sum;
int mid=(l+r)>>1;pushdown(x,tong(l,mid),tong(mid+1,r));
if(rr<=mid)return findans(tr[x].lc,l,mid,ll,rr);
else if(mid<ll)return findans(tr[x].rc,mid+1,r,ll,rr);
else return findans(tr[x].lc,l,mid,ll,mid)+findans(tr[x].rc,mid+1,r,mid+1,rr);
}
struct Query
{
int x,y,z/*-1表示保存,大于0则表示中点*/,tim/*-表示保存,+表示操作*/;
}qu[N];
int *li[NN];int top,cnt;
inline bool cmp(int *x,int *y){return (*x)<(*y);}
int n,m;
double ener;
char st[20];
int main()
{
scanf("%d%lf",&n,&p);
scanf("%d",&m);
li[top=1]=&n;cnt=0;
for(int i=1;i<=m;i++)
{
scanf("%d%s%d%d",&qu[i].tim,st+1,&qu[i].x,&qu[i].y);
if(st[1]=='s')qu[i].z=-1;
else
{
int l=qu[i].x-qu[i].y+1,r=qu[i].x+qu[i].y-1;
qu[i].z=qu[i].x;qu[i].x=l;qu[i].y=r;
li[++top]=&qu[i].z;
}
li[++top]=&qu[i].x;li[++top]=&qu[i].y;
}
sort(li+1,li+top+1,cmp);
cnt=0;be[0]=0;
for(int i=1;i<=top;i++)
{
if(*li[i]>be[cnt])
{
if(*li[i]==be[cnt]+1)be[cnt+1]=be[cnt]+1,cnt++;
else be[cnt+1]=*li[i]-1,be[cnt+2]=*li[i],cnt+=2;
}
*li[i]=cnt;
}
bt(1,cnt);
for(int i=1;i<=m;i++)
{
change1(1,1,cnt,1,cnt,(qu[i].tim-qu[i-1].tim)*p,0);
if(qu[i].z==-1)
{
int l=qu[i].x,r=qu[i].y;
ener+=findans(1,1,cnt,l,r);
change2(1,1,cnt,l,r);
printf("%.6lf\n",ener);
}
else
{
int l=qu[i].x,r=qu[i].y,mid=qu[i].z;double d=tong(l,mid);
double x=ener/(d*d);ener=0;
change1(1,1,cnt,l,mid,0,x);change1(1,1,cnt,mid+1,r,d*x,-x);
}
}
return 0;
}