hdu4533 线段树维护分段函数

时间:2021-08-19 07:05:57

更新:x1,y1,x2,y2不用long long 会wa。。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define maxn 200005
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ll long long
ll A[maxn<<],B[maxn<<],C[maxn<<];//系数a,b,c在t[l,r]区间的取值 inline void pushdown(int rt){
A[rt<<]+=A[rt];A[rt<<|]+=A[rt];
B[rt<<]+=B[rt];B[rt<<|]+=B[rt];
C[rt<<]+=C[rt];C[rt<<|]+=C[rt];
A[rt]=B[rt]=C[rt]=;
}
//区间【L,R】的a,b,c更新
void update(int L,int R,int l,int r,int rt,ll a,ll b,ll c){
if(L<=l && R>=r){
A[rt]+=a;
B[rt]+=b;
C[rt]+=c;
return;
}
int m=l+r>>;
if(L<=m) update(L,R,lson,a,b,c);
if(R>m) update(L,R,rson,a,b,c);
}
//询问t小于等于pos的一元二次式的值
ll query(ll t,int l,int r,int rt){
if(l==r){
return A[rt]*t*t+B[rt]*t+C[rt];
}
pushdown(rt);
int m=l+r>>;
if(t<=m) return query(t,lson);
else return query(t,rson);
}
void solve(ll x1,ll y1,ll x2,ll y2){
//t如果大于max(x2,y2),那么就是覆盖了整块被子,此时a,b皆为0
update(max(x2,y2)+,maxn,,maxn,,,,(x2-x1)*(y2-y1));
//a为0的状态
if(x2<y2)//t先触碰到右边,那么t在max(x2,y1)+1到y2之间一直是线性增长的
update(max(x2,y1)+,y2,,maxn,,,x2-x1,y1*(x1-x2));
else //t先触碰到上边,那么t在max(x1,y2)+1到x2之间一直是线性增长的
update(max(x1,y2)+,x2,,maxn,,,-y1+y2,x1*(y1-y2));
//最后的情况,三个系数都不是0
if(max(x1,y1)<min(x2,y2))
update(max(x1,y1),min(x2,y2),,maxn,,,-(x1+y1),x1*y1);
}
int main(){
int T,N;
ll x,t;
ll x1,y1,x2,y2;
cin >> T;
while(T--){
memset(A,,sizeof A);
memset(B,,sizeof B);
memset(C,,sizeof C); scanf("%d",&N);
for(int i=;i<=N;i++){
scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);
solve(x1,y1,x2,y2);
}
scanf("%lld",&x);
while(x--){
scanf("%lld",&t);
printf("%lld\n",query(t,,maxn,));
}
}
return ;
}

wa了,为什么呢

/**
推公式就完事了
要推出关于t的一元二次方程的值a,b,c关于t的函数,即t的分段函数
*/
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define maxn 200005
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ll long long
ll A[maxn<<],B[maxn<<],C[maxn<<];//系数a,b,c在t[l,r]区间的取值 inline void pushdown(int rt){
A[rt<<]+=A[rt];A[rt<<|]+=A[rt];
B[rt<<]+=B[rt];B[rt<<|]+=B[rt];
C[rt<<]+=C[rt];C[rt<<|]+=C[rt];
A[rt]=B[rt]=C[rt]=;
}
//区间【L,R】的a,b,c更新
void update(int L,int R,int l,int r,int rt,ll a,ll b,ll c){
if(L<=l && R>=r){
A[rt]+=a;
B[rt]+=b;
C[rt]+=c;
return;
}
int m=l+r>>;
if(L<=m) update(L,R,lson,a,b,c);
if(R>m) update(L,R,rson,a,b,c);
}
//询问t小于等于pos的一元二次式的值
ll query(ll t,int l,int r,int rt){
if(l==r){
return A[rt]*t*t+B[rt]*t+C[rt];
}
pushdown(rt);
int m=l+r>>;
if(t<=m) return query(t,lson);
else return query(t,rson);
}
void solve(int x1,int y1,int x2,int y2){
//t如果大于max(x2,y2),那么就是覆盖了整块被子,此时a,b皆为0
update(max(x2,y2)+,maxn,,maxn,,,,(x2-x1)*(y2-y1));
//a为0的状态
if(x2<y2)//t先触碰到右边,那么t在max(x2,y1)+1到y2之间一直是线性增长的
update(max(x2,y1)+,y2,,maxn,,,x2-x1,y1*(x1-x2));
else //t先触碰到上边,那么t在max(x1,y2)+1到x2之间一直是线性增长的
update(max(x1,y2)+,x2,,maxn,,,-y1+y2,x1*(y1-y2));
//最后的情况,三个系数都不是0
if(max(x1,y1)<min(x2,y2))
update(max(x1,y1),min(x2,y2),,maxn,,,-(x1+y1),x1*y1);
}
int main(){
int T,N;
ll x,t;
int x1,y1,x2,y2;
cin >> T;
while(T--){
memset(A,,sizeof A);
memset(B,,sizeof B);
memset(C,,sizeof C); scanf("%d",&N);
for(int i=;i<=N;i++){
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
solve(x1,y1,x2,y2);
}
scanf("%lld",&x);
while(x--){
scanf("%lld",&t);
printf("%lld\n",query(t,,maxn,));
}
}
return ;
}