题目描述
You are a denizen of Linetopia, whose n major cities happen to be equally spaced along an east-west line. In fact, they are often numbered in order from 1 to n, where 1 is the westmost city and n is the eastmost city.
Linetopia was a lovely place to live until forces from neighboring Trapez invaded. As part of Linetopia’s Shielding Lives and Protecting Citizens initiative, you have been called upon to process information about Trapezoid troop movements so we can determine which cities have been hardest hit and know where to send reinforcements.
Linetopia intelligence has discovered that the Trapezoid forces are attacking in the following pattern. They are sending massive aircraft to drop troops on Linetopia cities. Each aircraft starts at some city i, dropping s soldiers. The aircraft then proceeds to fly either east or west. Each time it flies over another city, it drops a more soldiers than it dropped on the previous city it passed. After performing d drops, the aircraft returns to Trapez to resupply.
You will be receiving intel updates that inform you of the specs of each Trapezoid aircraft passing over Linetopia. You want to answer queries that ask how many Trapezoid troops have been dropped on a particular city. Are you up to the task?
输入
The first line of input contains a single integer T (1 ≤ T ≤ 10), the number of test cases. The first line of each test case contains two integers: m (1 ≤ m ≤ 10,000), the number of updates and queries and n (1 ≤ n ≤ 500,000), the number of cities in Linetopia.
The next m lines of input are either updates or queries. Update lines begin with a capital U, then contain either a capital E (east) or W (west) to indicate direction, and then contain four integers i (1 ≤ i ≤ n), s (1 ≤ s ≤ 10,000), a (0 ≤ a ≤ 10,000), and d (1 ≤ d ≤ n). These integers signify the starting city, the starting number of soldiers, the increase in soldiers per city, and the number of drops, respectively. You can assume d never results in an aircraft flying to the west of city 1 or to the east of city n.
Query lines begin with a capital Q, and then contain a single integer i (1 ≤ i ≤ n) indicating the city being queried.
输出
For each query in the input, output a single line containing the number of Trapezoid troops dropped in that city.
题目大意:
emmmm,简化题意,就是有n个点,初始化的时候这n个点的值全是0,m次操作,每次操作只有两种–查询和更新,这里的查询是单点去查询,更改是区间更改,U 开头的代表区间更新,Q开头的代表单点查询
U E i s a d代表从i号城市开始,从左向右赋值d次,每一次的赋值呈一个等差数列 ,且第i个开始的数值也就是首项为s,比如样例:
开始的时候是 0 0 0
经过第一次的修改以后变成 5 7 9,这就呈一个等差数列
那么在去解释一下 :U W i s a d 就是 以i为起点,从右向左去做一个等差数列
分析:首先这是一个区间问题,可以去向线段树去靠,但是线段树维护的区间值是一个区间相同的值,这题每个区间的修改是没有办法去整体维护的,必须去单点的线段树的维护,那么就会造成每次的维护区间的值都是到叶子结点,线段树的复杂度是nlog(n)的,那么每次去修改单点,那么就会造成时间超限;
对于区间的问题还有一种东西就是—差分数组,对于差分数组它的数据结构的特点在这里就不在赘述了,那么就假设都是知道滴(^__ ^)
简单解释一下吧:差分数组的每一个值是两项之间的差值,前i项的和就是第i个的数值
对于这道题目来说,正好的是差分数组的值是一个定值,因为给出的数列是一个等差数列嘛,还是拿样例来说:
下标 | 1 | 2 | 3 | 4 |
---|---|---|---|---|
初始值 | 0 | 0 | 0 | 0 |
第一次修改后的值 | 5 | 7 | 9 | 0 |
第一次得到的差分数组 | 5 | 2 | 2 | -2 |
第二次修改后的值(不加到第一次数中) | 0 | 20 | 10 | 0 |
第二次得到的差分数组 | 0 | 20 | -10 | -10 |
根据这个表,我们可以去维护这个差分数组,在维护的过程中通过修改这个差分数组然后去获得差分数组的前缀和就能得到任何一个单点的值
在维护更新差分数组的时候要对端点特殊处理一下,还有要注意的地方就是线段树的区间是[1,n+1](这是根据差分数组的特性来决定的)
#include <iostream>
#include <algorithm>
#include <string>
#include <map>
#include <cstring>
#include <cmath>
#include <queue>
#include <cstdio>
#include <vector>
#include <set>
#include <iomanip>
#include <stack>
using namespace std;
typedef long long ll;
const int N = 5e5+100;
const int INF=0x3f3f3f3f;
const ll LINF=0x3f3f3f3f3f3f3f3f;
const int MOD=1e9+7;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Abs(x) ((x)>=0?(x):-(x))
#define rson id<<1|1
#define lson id<<1
ll d[N<<2],sum[N<<2],lazy[N<<2];
void push_down(int id,int l,int r){
int mid=(l+r)>>1;
if(lazy[id]!=0){
lazy[lson]+=lazy[id];
lazy[rson]+=lazy[id];
d[lson]+=lazy[id];
d[rson]+=lazy[id];
sum[lson]+=lazy[id]*(mid-l+1);
sum[rson]+=lazy[id]*(r-mid);
lazy[id]=0;
}
}
void update(int id,int L,int R,int l,int r,ll val){
if(l==L&&R==r){
lazy[id]+=val;
d[id]+=val;
sum[id]+=val*(r-l+1);//这个地方是需要相乘区间长度的,push_down()函数里面也是这个意思
return ;
}
int mid=(L+R)>>1;
push_down(id,L,R);
if(r<=mid)
update(lson,L,mid,l,r,val);
else if(l>mid)
update(rson,mid+1,R,l,r,val);
else{
update(lson,L,mid,l,mid,val);
update(rson,mid+1,R,mid+1,r,val);
}
sum[id]=sum[lson]+sum[rson];
}
ll query(int id,int L,int R,int l,int r){
if(l==L&&r==R){
return sum[id];
}
int mid=(L+R)>>1;
push_down(id,L,R);
if(r<=mid)
return query(lson,L,mid,l,r);
else if(l>mid)
return query(rson,mid+1,R,l,r);
else
return query(lson,L,mid,l,mid)+query(rson,mid+1,R,mid+1,r);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif // ONLINE_JUDGE
int t;
scanf("%d",&t);
while(t--){
memset(d,0,sizeof d);
memset(sum,0,sizeof sum);
memset(lazy,0,sizeof lazy);
int n,m;
scanf("%d%d\n",&m,&n);
while(m--){char c1,c2;
scanf("%c%*c",&c1);
if(c1=='U'){
scanf("%c",&c2);
ll stid,stnum,dd,num;//三者分别对应题目当中的i s a d
scanf("%lld%lld%lld%lld\n",&stid,&stnum,&dd,&num);
if(c2=='E'){
update(1,1,n+1,stid,stid,stnum);
if(num!=1)
update(1,1,n+1,stid+1,stid+num-1,dd);
update(1,1,n+1,stid+num,stid+num,-(stnum+dd*(num-1)));
}else{
update(1,1,n+1,stid-num+1,stid-num+1,stnum+dd*(num-1));
if(num!=1){
update(1,1,n+1,stid-num+2,stid,-dd);
}
update(1,1,n+1,stid+1,stid+1,-stnum);
}
}else{int u;
scanf("%d\n",&u);
printf("%lld\n",query(1,1,n+1,1,u));
}
}
}
return 0;
}
下面是几组数据
1
4 10
U E 3 5 2 3
Q 3
Q 4
Q 5
5
7
9
3
8 3
U E 1 5 2 3
Q 1
Q 2
Q 3
U W 3 10 10 2
Q 1
Q 2
Q 3
9 3
U W 1 1000 10 1
Q 1
Q 2
Q 3
U E 1 5 2 2
Q 3
U W 2 10 10 2
Q 1
Q 2
8 3
U W 2 10 100 1
Q 1
Q 2
Q 3
U E 1 5 2 3
Q 1
Q 2
Q 3
5
7
9
5
27
19
1000
0
0
0
1025
17
0
10
0
5
17
9