风力观测
发布时间: 2017年7月9日 18:17 最后更新: 2017年7月9日 21:04 时间限制: 1000ms 内存限制: 128M
小Y正在观测y地区的风力情况,他在一条直线上依此设定了n 个观测点,并观测与直线垂直方向的风力值,风力有时是正向的也有时是反向的,规定正向时的风力值为正数,他发现每次风力值的变化都可以表示为观测点上一条线段[L,R] 上的同时增强或者减弱。小Y希望能够实时统计这些观测点的数据,并且实时分析这些观测点在历史中到达的风力最大绝对值,但是他无法同时对大量的观测点进行分析, 更重要的是他记不住这些观测点过去的风力大小,于是他希望你来用计算机帮助他完成这个任务。
你简化了这个问题,将问题分为两种查询:
1.对观测点[L,R] 上的风力正向增强X 。(X 为负数表示正向减弱,即反向加强)
2.查询观测点A 上的历史风力最大绝对值。
第一行有一个整数T 表示数据组数。(T<=10 )
接着有T
组数据,每组数据第一行是整数n
和q
,表示观测点个数和查询次数。
第二行有n
个数a 1 ,...,a n
,表示每个观测点的风力初始值。
接着有q
行,表示q
次操作,格式为:
1 L R X:表示对[L,R]
线段上的正向风力同时增强x
。
2 A:表示查询A
点的历史风力最大绝对值。
1<=n,q<=100000
。
1<=L,R,A<=n
−10000<=a i
, X<=10000
对每次询问2,输出一个数字表示风力值并换行。
复制
1 5 6 1 -1 2 3 -3 1 1 5 1 2 1 2 2 1 2 4 -5 2 2 2 3
2 1 5 3
分析:考虑按时间点建线段树,但是位置点太多,还需要离线一下;
所以方法就是离线处理,类似扫描线一样把区间处理,查询全部按端点存储;
这样对每个询问就是求当前线段树中从起始时间到询问时间点最大的前缀和;
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <algorithm> #include <climits> #include <cstring> #include <string> #include <set> #include <bitset> #include <map> #include <queue> #include <stack> #include <vector> #include <cassert> #include <ctime> #define rep(i,m,n) for(i=m;i<=(int)n;i++) #define mod 1000000007 #define inf 0x3f3f3f3f #define vi vector<int> #define pb push_back #define mp make_pair #define fi first #define se second #define ll long long #define pi acos(-1.0) #define pii pair<int,int> #define sys system("pause") #define ls rt<<1 #define rs rt<<1|1 const int maxn=1e5+10; const int N=5e2+10; using namespace std; ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);} ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p%mod;p=p*p%mod;q>>=1;}return f;} int n,m,k,t,pq[maxn]; ll ma[maxn<<2],mi[maxn<<2],tag[maxn<<2],a[maxn],ret[maxn]; vi qu[maxn]; vector<pii>ql[maxn],qr[maxn]; void pdw(int rt) { ma[ls]+=tag[rt]; mi[ls]+=tag[rt]; tag[ls]+=tag[rt]; ma[rs]+=tag[rt]; mi[rs]+=tag[rt]; tag[rs]+=tag[rt]; tag[rt]=0; } void pup(int rt) { ma[rt]=max(ma[ls],ma[rs]); mi[rt]=min(mi[ls],mi[rs]); tag[rt]=0; } void build(int l,int r,int rt) { ma[rt]=mi[rt]=tag[rt]=0; if(l==r)return; int mid=l+r>>1; build(l,mid,ls); build(mid+1,r,rs); } void upd(int L,int R,ll v,int l,int r,int rt) { if(L==l&&R==r) { tag[rt]+=v; ma[rt]+=v; mi[rt]+=v; return; } int mid=l+r>>1; if(tag[rt])pdw(rt); if(R<=mid)upd(L,R,v,l,mid,ls); else if(L>mid)upd(L,R,v,mid+1,r,rs); else upd(L,mid,v,l,mid,ls),upd(mid+1,R,v,mid+1,r,rs); pup(rt); } pair<ll,ll>gao(int L,int R,int l,int r,int rt) { if(L==l&&R==r)return mp(ma[rt],mi[rt]); int mid=l+r>>1; if(tag[rt])pdw(rt); if(R<=mid)return gao(L,R,l,mid,ls); else if(L>mid)return gao(L,R,mid+1,r,rs); else { pair<ll,ll>pl=gao(L,mid,l,mid,ls); pair<ll,ll>pr=gao(mid+1,R,mid+1,r,rs); return mp(max(pl.fi,pr.fi),min(pl.se,pr.se)); } } int main() { int i,j; scanf("%d",&t); while(t--) { int q; scanf("%d%d",&n,&q); rep(i,1,n)scanf("%lld",&a[i]),qu[i].clear(),ql[i].clear(),qr[i].clear(); pq[0]=0; build(1,q,1); rep(i,1,q) { int op,x,y,z; scanf("%d%d",&op,&x); if(op==1)scanf("%d%d",&y,&z),ql[x].pb(mp(i,z)),qr[y].pb(mp(i,z)); else qu[x].pb(i),pq[++pq[0]]=i; } rep(i,1,n) { rep(j,0,ql[i].size()-1)upd(ql[i][j].fi,q,ql[i][j].se,1,q,1); rep(j,0,qu[i].size()-1) { pair<ll,ll>x=gao(1,qu[i][j],1,q,1); x.fi=max(x.fi,0ll); x.se=min(x.se,0ll); ret[qu[i][j]]=max(abs(a[i]+x.fi),abs(a[i]+x.se)); } rep(j,0,qr[i].size()-1)upd(qr[i][j].fi,q,-qr[i][j].se,1,q,1); } rep(i,1,pq[0])printf("%lld ",ret[pq[i]]); } return 0; }