Description
给定N个向量v
需要支持两种操作,修改某一个向量
或者对于一个区间
×代表向量叉积
Solution
因为(xi,yi)×(xj,yj)=xiyj−xjyi
平方式子拆出来
=x2iy2j−2xiyixjyj+x2jy2i
对于每个次询问维护x2,y2,xy的前缀和即可
这样是O(N2)的
考虑优化
i<j太麻烦,不妨去掉这个限制,最后再除以2
那就非常方便处理了
设Sx=∑x2,Sy=∑y2,Sc=∑xy
那么区间的答案容易得出就是2SxSy−2Sc22
也就是SxSy−Sc2
树状数组维护一下即可
Code
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
#define N 1000005
#define LL long long
#define mo 20170927
using namespace std;
LL c[3][N],a[N],b[N];
int n,m;
int lowbit(int k)
{
return k&(-k);
}
void put(int k,LL v,int q)
{
while(k<=n) (c[q][k]+=v)%=mo,k+=lowbit(k);
}
LL get(int k,int q)
{
LL s=0;
while(k) (s+=c[q][k])%=mo,k-=lowbit(k);
return s;
}
int main()
{
freopen("kurisu.in","r",stdin);
freopen("kurisu.out","w",stdout);
cin>>n>>m;
fo(i,1,n) scanf("%lld%lld",&a[i],&b[i]),put(i,a[i]*a[i]%mo,0),put(i,b[i]*b[i]%mo,1),put(i,a[i]*b[i]%mo,2);
LL ny=10085464;
fo(i,1,m)
{
int p,v;
LL l,r;
scanf("%d",&v);
if(v==1)
{
scanf("%d%lld%lld",&p,&l,&r);
put(p,(l*l%mo-a[p]*a[p])%mo,0),put(p,(r*r%mo-b[p]*b[p]%mo)%mo,1),put(p,(l*r%mo-a[p]*b[p]%mo)%mo,2);
a[p]=l,b[p]=r;
}
else
{
scanf("%lld%lld",&l,&r);
LL s1=(get(r,0)-get(l-1,0)+mo)%mo,s2=(get(r,1)-get(l-1,1)+mo)%mo,sc=(get(r,2)-get(l-1,2)+mo)%mo;
printf("%lld\n",(s1*s2%mo-sc*sc%mo+(LL)5*mo)%mo);
}
}
}