题解:P6588 『JROI-1』 向量
显而易见,这是一道线段树的题,并且是单点修改,区间查询。
操作一道操作三均为线段树基本操作,这里不展开讲了。
操作四和操作五不好直接推导,所以我们可以从线段树的角度下手。
对于一个区间
- 两个向量都在左区间。那么它们的值就是
\sum\limits_{i=l}^{mid-1}\sum\limits_{j=i+1}^{mid}\overrightarrow{a_i}\cdot\overrightarrow{a_j} ; - 两个向量都在右区间。那么它们的值就是
\sum\limits_{i=mid+1}^{r-1}\sum\limits_{j=i+1}^{r}\overrightarrow{a_i}\cdot\overrightarrow{a_j} ; - 一个点在左区间,一个点在右区间。这些点的值为
\sum\limits_{i=l}^{mid}\sum\limits_{j=mid+1}^{r}\overrightarrow{a_i}\cdot\overrightarrow{a_j} 。这时因为\overrightarrow{a_i} 和\overrightarrow{a_j} 是独立的,可以进一步将式子变形成\left(\sum\limits_{i=l}^{mid}x_i\right)\cdot\left(\sum\limits_{j=mid+1}^{r}x_j\right)+\left(\sum\limits_{i=l}^{mid} y_i\right)\cdot\left(\sum\limits_{j=mid+1}^{r}y_j\right) 。这里因为每一个求和都是独立的,所以可以直接用左右儿子的区间和算出来。
最后递归合并即可。叉积同理。
submission
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=1e5+5;
struct node{
int l,r,x,y,dot,cross;
}t[maxn<<2];
struct node1{
int x,y;
}a[maxn];
int n,m;
node pushup(node L,node R){
node res;
res.l=L.l,res.r=R.r;
res.x=L.x+R.x,res.y=L.y+R.y;
res.dot=L.dot+R.dot+L.x*R.x+L.y*R.y;
res.cross=L.cross+R.cross+L.x*R.y-L.y*R.x;
return res;
}
void build(int p,int l,int r){
t[p].l=l,t[p].r=r,t[p].dot=t[p].cross=0;
if(l==r){
t[p].x=a[l].x,t[p].y=a[l].y;
return;
}
int mid=l+r>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
t[p]=pushup(t[p<<1],t[p<<1|1]);
}
void add(int p,int x,node1 k){
if(t[p].l==t[p].r){
t[p].x+=k.x,t[p].y+=k.y;
return;
}
int mid=t[p].l+t[p].r>>1;
if(x<=mid)add(p<<1,x,k);
else add(p<<1|1,x,k);
t[p]=pushup(t[p<<1],t[p<<1|1]);
}
void mul(int p,int x,int k){
if(t[p].l==t[p].r){
t[p].x*=k,t[p].y*=k;
return;
}
int mid=t[p].l+t[p].r>>1;
if(x<=mid)mul(p<<1,x,k);
else mul(p<<1|1,x,k);
t[p]=pushup(t[p<<1],t[p<<1|1]);
}
node query(int p,int l,int r){
if(l<=t[p].l&&t[p].r<=r)return t[p];
int mid=t[p].l+t[p].r>>1;
if(r<=mid)return query(p<<1,l,r);
if(l>mid)return query(p<<1|1,l,r);
return pushup(query(p<<1,l,r),query(p<<1|1,l,r));
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>a[i].x>>a[i].y;
build(1,1,n);
while(m--){
int op,i,tt,l,r;
node1 k;
cin>>op;
if(op==1){
cin>>i>>k.x>>k.y;
add(1,i,k);
}else if(op==2){
cin>>i>>k.x>>k.y;
k.x=-k.x,k.y=-k.y;
add(1,i,k);
}else if(op==3){
cin>>i>>tt;
mul(1,i,tt);
}else if(op==4){
cin>>l>>r;
cout<<query(1,l,r).dot<<"\n";
}else if(op==5){
cin>>l>>r;
cout<<query(1,l,r).cross<<"\n";
}
}
}