Description

-
n
<
=
2
e
5
,
∣
v
∣
≤
5000
n<=2e5,|v|\le5000
n<=2e5,∣v∣≤5000
Solution
- 对于虚数的相乘,是模长相乘、极角相加的,最后是质数模长
∣
p
∣
2
|p|^2
∣p∣2,所以最多有两个数相乘形成这个质数。
- 不妨考虑对于还未到两个因子的复数暴力乘,由于势能一定,所以时间是可以满足的。
- 又因为有区间赋值,所以我们可以用一个平衡树来进行块的合并(set也可以)。
- 再考虑不贡献模长的四种数,
1
,
−
1
,
i
,
−
i
1,-1,i,-i
1,−1,i,−i,多维护
4
4
4个东西表示四个方向上的质数有哪些,以及tag还要有当前转了多少度。
- 以上可以用线段树做到两个log,看起来线段树要好打一点(
- 注意一系列tag下放对于答案的影响(至于其他若干弱智错误每一个就要花我十几分钟)。
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<ctime>
#define maxn 200005
#define maxm 50000005
using namespace std;
int n,q,i,j,k;
struct Z{int x,y,c;Z(int _x=0,int _y=0,int _c=0){x=_x,y=_y,c=_c;}} fx[4];
Z operator*(Z a,Z b){
if (a.c+b.c>2) return Z(0,0,3);
return Z(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x,a.c+b.c);
}
Z a[maxn],t[maxn*4]; int c[maxn*4],bz[maxn*4],s[maxn*4][4],tag[maxn*4];
void read(int &x){
x=0; char ch=getchar(); int t=1;
for(;(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if (ch=='-') t=-1,ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
x=x*t;
}
int tot,pri[maxm],isp[maxm];
void getpri(){
isp[0]=isp[1]=1;
for(i=2;i<maxm;i++){
if (!isp[i]) pri[++tot]=i;
for(j=1;j<=tot&&i*pri[j]<maxm;j++){
isp[i*pri[j]]=1;
if (i%pri[j]==0) break;
}
}
}
void check(int x,int l,int r){
Z a=t[x]*fx[tag[x]];
s[x][0]=s[x][1]=s[x][2]=s[x][3]=0;
if (a.x==0&&!isp[abs(a.y)]) s[x][(a.y>0)?1:3]+=(r-l+1);
if (a.y==0&&!isp[abs(a.x)]) s[x][(a.x>0)?0:2]+=(r-l+1);
}
void upd(int x){
int l=x<<1,r=x<<1^1;
c[x]=c[l]+c[r];
s[x][0]=s[l][0]+s[r][0],s[x][1]=s[l][1]+s[r][1];
s[x][2]=s[l][2]+s[r][2],s[x][3]=s[l][3]+s[r][3];
}
int tmp[4];
void downtag(int x,int l,int r){
if (bz[x]){
int mid=(l+r)>>1;
t[x<<1]=t[x],bz[x<<1]=1,tag[x<<1]=tag[x],c[x<<1]=(c[x]>0)*(mid-l+1);
t[x<<1^1]=t[x],bz[x<<1^1]=1,tag[x<<1^1]=tag[x],c[x<<1^1]=(c[x]>0)*(r-mid);
for(int k=0;k<4;k++) {
s[x<<1][k]=(s[x][k]>0)*(mid-l+1);
s[x<<1^1][k]=(s[x][k]>0)*(r-mid);
}
bz[x]=0,t[x]=Z(0,0,0),tag[x]=0;
} else
if (tag[x]) {
for(int k=0;k<4;k++) tmp[(k+tag[x])%4]=s[x<<1][k];
memcpy(s[x<<1],tmp,sizeof(tmp));
for(int k=0;k<4;k++) tmp[(k+tag[x])%4]=s[x<<1^1][k];
memcpy(s[x<<1^1],tmp,sizeof(tmp));
(tag[x<<1]+=tag[x])%=4,(tag[x<<1^1]+=tag[x])%=4,tag[x]=0;
}
}
void maketree(int x,int l,int r){
if (l==r) {
bz[x]=1;
if (!a[l].x&&!a[l].y) c[x]=0; else {
c[x]=1;
if (!a[l].x&&abs(a[l].y)==1) t[x]=Z(1,0,0),tag[x]=(a[l].y<0)?3:1; else
if (!a[l].y&&abs(a[l].x)==1) t[x]=Z(1,0,0),tag[x]=(a[l].x>0)?0:2; else
t[x]=a[l],t[x].c=1,tag[x]=0;
}
check(x,l,r);
return;
}
int mid=(l+r)>>1;
maketree(x<<1,l,mid),maketree(x<<1^1,mid+1,r);
upd(x);
}
void add(int x,int l,int r,int L,int R,int d){
if (l>R||r<L) return;
if (L<=l&&r<=R) {
for(int k=0;k<4;k++) tmp[(k+d)%4]=s[x][k];
memcpy(s[x],tmp,sizeof(tmp)),(tag[x]+=d)%=4;
return;
}
downtag(x,l,r);
int mid=(l+r)>>1;
add(x<<1,l,mid,L,R,d),add(x<<1^1,mid+1,r,L,R,d);
upd(x);
}
void mul(int x,int l,int r,int L,int R,Z v){
if (l>R||r<L) return;
if (!c[x]) return;
if (L<=l&&r<=R&&bz[x]) {
t[x]=t[x]*v,c[x]=(t[x].c<=2)*(r-l+1),check(x,l,r);
return;
}
downtag(x,l,r);
int mid=(l+r)>>1;
mul(x<<1,l,mid,L,R,v),mul(x<<1^1,mid+1,r,L,R,v);
upd(x);
}
void cover(int x,int l,int r,int L,int R,Z v){
if (l>R||r<L) return;
if (L<=l&&r<=R) {
bz[x]=1,t[x]=v,tag[x]=0,c[x]=(t[x].c<=2)*(r-l+1);
check(x,l,r);
return;
}
downtag(x,l,r);
int mid=(l+r)>>1;
cover(x<<1,l,mid,L,R,v);
cover(x<<1^1,mid+1,r,L,R,v);
upd(x);
}
int find(int x,int l,int r,int L,int R){
if (l>R||r<L) return 0;
if (L<=l&&r<=R) return s[x][0];
downtag(x,l,r);
int mid=(l+r)>>1;
return find(x<<1,l,mid,L,R)+find(x<<1^1,mid+1,r,L,R);
}
int main(){
freopen("ceshi.in","r",stdin);
freopen("ceshi.out","w",stdout);
read(n),read(q),getpri();
fx[0]=Z(1,0,0),fx[1]=Z(0,1,0),fx[2]=Z(-1,0,0),fx[3]=Z(0,-1,0);
for(i=1;i<=n;i++) read(a[i].x),read(a[i].y);
maketree(1,1,n);
while (q--){
int opt,l,r; Z v; read(opt),read(l),read(r);
if (opt==1) {
read(v.x),read(v.y);
if (!v.x&&!v.y) v.c=3; else
if (!v.x&&abs(v.y)==1||!v.y&&abs(v.x)==1) v.c=0; else
v.c=1;
cover(1,1,n,l,r,v);
} else
if (opt==2){
read(v.x),read(v.y);
if (!v.x&&!v.y) v.c=3,mul(1,1,n,l,r,v); else
if (!v.x&&abs(v.y)==1) add(1,1,n,l,r,(v.y>0)?1:3); else
if (!v.y&&abs(v.x)==1) add(1,1,n,l,r,(v.x>0)?0:2); else
v.c=1,mul(1,1,n,l,r,v);
}
else printf("%d\n",find(1,1,n,l,r));
}
}