您的位置:首页 > 其它

BZOJ4785 [Zjoi2017]树状数组

2017-03-28 17:19 435 查看
扯淡:

昨天就在BZOJ上看到了题,但是光老师说今天考ZJOI的题,就一直没看

看完题看了看部分分,所有修改在所有询问之前?那这题是不是肯定是cdq啊

然后YYYY,YY了一个贼JB恶心的CDQ,写了9000B,然后发现我们测的时候开4秒,觉得在校OJ上4秒肯定跑不过就交了70分暴力

后来考试结束了发现标程跑了3秒9……于是把时限开到8s,6s就过了

如果上天再给我一次机会,我一定写一个树套树,不知道好写到哪里去了,常数也小

做法:

首先可以发现这个树状数组其实求的是后缀和

然后嘛,如果询问的l不等于1,则相当于询问l-1和r相等的概率,如果l等于一,就相当于询问1~r-1的和与r+1到n的和相等的概率

l等于1和不等于1差不多,都是下面做法,但是要分开

那么考虑朴素做法,每次查询的时候枚举所有修改,计算一下影响即可

比如l等于1的情况,那么考虑比如修改的区间是l~r,查询的右端点在l~r之间

那么p会变成p/(r-l+1)+(1-p)*(r-l)/(r-l+1)

其他的情况类似考虑

发现一次修改的影响就相当于把概率乘一个数再加一个数

而把询问的左端点看成横坐标,右端点看成纵坐标,修改就相当于矩形乘加,拿cdq或者线段树维护即可

因为这题的特殊性质,所以不同的乘加之间顺序是无所谓的,所以cdq也是可行的

#include<iostream>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<cstdlib>
#include<cstdio>
#include<map>
#include<bitset>
#include<set>
#include<stack>
#include<vector>
#include<queue>
using namespace std;
#define MAXN 300010
#define MAXM 1010
#define ll long long
#define eps 1e-8
#define MOD 998244353
#define INF 1000000000
char xB[1<<15],*xS=xB,*xTT=xB;
#define getc() (xS==xTT&&(xTT=(xS=xB)+fread(xB,1,1<<15,stdin),xS==xTT)?0:*xS++)
#define isd(c) (c>='0'&&c<='9')
int read(){
char xchh;
int xaa;
while(xchh=getc(),!isd(xchh));(xaa=xchh-'0');
while(xchh=getc(),isd(xchh))xaa=xaa*10+xchh-'0';return xaa;
}
struct que{
ll x;
ll y;
ll c;
ll tim;
ll A11,B11,A12,B12,A21,B21,A22,B22;
ll nA11,nA12,nA21,nA22;
};
int n,m;
ll L[MAXN],R[MAXN];
ll ine[MAXN];
que a[MAXN];
que ta[MAXN];
int tot;
ll ans[MAXN];
ll ch[MAXN<<2],ad[MAXN<<2],col[MAXN<<2],flg[MAXN<<2];
bool qinding[MAXN];
ll frog[MAXN];
int son[MAXN<<2][2];
int TOT,rt;
bool FLAG;
bool cmpl(que x,que y){
return x.x!=y.x?x.x<y.x:x.c>y.c;
}
void nn(int &x){
if(!x){
x=++TOT;
ch[x]=1;
ad[x]=0;
col[x]=-1;
flg[x]=0;
son[x][0]=son[x][1]=0;
}
}
ll mi(ll x,ll y){
ll re=1;
while(y){
if(y&1){
(re*=x)%=MOD;
}
(x*=x)%=MOD;
y>>=1;
}
return re;
}
inline void tomul(int &x,ll y){
nn(x);
(ch[x]*=y)%=MOD;
(ad[x]*=y)%=MOD;
}
inline void toad(int &x,ll y){
nn(x);
(ad[x]+=y)%=MOD;
}
inline void tocol(int &x,ll y){
nn(x);
col[x]=y;
}
inline void toch(int &x,ll y){
nn(x);
flg[x]+=y;
}
inline void pd(int &x){
if(ch[x]!=1){
tomul(son[x][0],ch[x]);
tomul(son[x][1],ch[x]);
ch[x]=1;
}
if(ad[x]){
toad(son[x][0],ad[x]);
toad(son[x][1],ad[x]);
ad[x]=0;
}
if(col[x]!=-1){
tocol(son[x][0],col[x]);
tocol(son[x][1],col[x]);
col[x]=-1;
}
}
void change1(int &x,int y,int z,int l,int r,ll cv){

if(l>r){
return ;
}
nn(x);
if(y==l&&z==r){
tomul(x,cv);
return ;
}
pd(x);
int mid=y+z>>1;
if(r<=mid){
change1(son[x][0],y,mid,l,r,cv);
}else if(l>mid){
change1(son[x][1],mid+1,z,l,r,cv);
}else{
change1(son[x][0],y,mid,l,mid,cv);
change1(son[x][1],mid+1,z,mid+1,r,cv);
}
}
void change2(int &x,int y,int z,int l,int r,ll cv){
if(l>r){
return ;
}
nn(x);
if(y==l&&z==r){
toad(x,cv);
return ;
}
pd(x);
int mid=y+z>>1;
if(r<=mid){
change2(son[x][0],y,mid,l,r,cv);
}else if(l>mid){
change2(son[x][1],mid+1,z,l,r,cv);
}else{
change2(son[x][0],y,mid,l,mid,cv);
change2(son[x][1],mid+1,z,mid+1,r,cv);
}
}
void change3(int &x,int y,int z,int l,int r,ll cv){
if(l>r){
return ;
}
nn(x);
if(y==l&&z==r){
tocol(x,cv);
return ;
}
pd(x);
int mid=y+z>>1;
if(r<=mid){
change3(son[x][0],y,mid,l,r,cv);
}else if(l>mid){
change3(son[x][1],mid+1,z,l,r,cv);
}else{
change3(son[x][0],y,mid,l,mid,cv);
change3(son[x][1],mid+1,z,mid+1,r,cv);
}
}
void change4(int &x,int y,int z,int l,int r,ll cv){
if(l>r){
return ;
}
nn(x);
if(y==l&&z==r){
toch(x,cv);
return ;
}
pd(x);
int mid=y+z>>1;
if(r<=mid){
change4(son[x][0],y,mid,l,r,cv);
}else if(l>mid){
change4(son[x][1],mid+1,z,l,r,cv);
}else{
change4(son[x][0],y,mid,l,mid,cv);
change4(son[x][1],mid+1,z,mid+1,r,cv);
}
}
ll ask(int &x,int y,int z,int p,bool flag,ll X){
nn(x);
if(y==z){
FLAG=flag||flg[x];
return (flag||flg[x])?col[x]:(ch[x]*X%MOD+ad[x])%MOD;
}
int mid=y+z>>1;
pd(x);
if(p<=mid){
return ask(son[x][0],y,mid,p,flag||flg[x],X);
}else{
return ask(son[x][1],mid+1,z,p,flag||flg[x],X);
}
}
void cdq(int L,int R,int l,int r){
if(L==R){
return ;
}
int MID=L+R>>1;
int i,j;
int mid=l-1;
for(i=l;i<=r;i++){
if(a[i].tim<=MID){
mid++;
}
}
int tl=l,tr=mid+1;
for(i=l;i<=r;i++){
if(a[i].tim<=MID){
ta[tl++]=a[i];
}else{
ta[tr++]=a[i];
}
}
memcpy(a+l,ta+l,sizeof(que)*(r-l+1));
cdq(L,MID,l,mid);
rt=TOT=0;
ll mul=1,ad=0;
bool FLG=0,FLG2=0;
for(i=l;i<=mid;i++){
if(a[i].c==0||a[i].c==-1){
FLG=1;
break;
}
}
for(i=mid+1;i<=r;i++){
if(a[i].c==1||a[i].c==2){
FLG2=1;
break;
}
}
if(FLG&&FLG2){
for(i=l;i<=mid;i++){
if(a[i].c==0){
(mul*=a[i].A11)%=MOD;
(ad*=a[i].A11)%=MOD;
(ad+=a[i].B11)%=MOD;
if(a[i].A22!=0){
change1(rt,1,n,a[i].x,a[i].y,a[i].A22);
change2(rt,1,n,a[i].x,a[i].y,a[i].B22);
}else{
change3(rt,1,n,a[i].x,a[i].y,a[i].B22);
change4(rt,1,n,a[i].x,a[i].y,1);
}
}
}
int flag=0;
ll ts;
bool fro=1;
for(i=l,j=mid+1;j<=r;j++){
while(i<=mid&&a[i].x<=a[j].x){
if(a[i].c==0){
fro=0;
(ad+=MOD-a[i].B11)%=MOD;
(mul*=a[i].nA11)%=MOD;
(ad*=a[i].nA11)%=MOD;
if(a[i].A12==0){
flag++;
ts=a[i].B12;
}else{
(mul*=a[i].A12)%=MOD;
(ad*=a[i].A12)%=MOD;
(ad+=a[i].B12)%=MOD;
}
if(a[i].A22!=0){
change2(rt,1,n,a[i].x,a[i].y,MOD-a[i].B22);
change1(rt,1,n,a[i].x,a[i].y,a[i].nA22);
change1(rt,1,n,a[i].y+1,n,a[i].A22);
change2(rt,1,n,a[i].y+1,n,a[i].B22);
}else{
change4(rt,1,n,a[i].x,a[i].y,-1);
change3(rt,1,n,a[i].y+1,n,a[i].B22);
change4(rt,1,n,a[i].y+1,n,1);
}
if(a[i].A11!=0){
change1(rt,1,n,a[i].x,a[i].y,a[i].A21);
change2(rt,1,n,a[i].x,a[i].y,a[i].B21);
}else{
change3(rt,1,n,a[i].x,a[i].y,a[i].B21);
change4(rt,1,n,a[i].x,a[i].y,1);
}
}
if(a[i].c==-1){
if(fro){
i++;
continue ;
}
if(a[i].nA12==0){
flag--;
}else{
(ad+=MOD-a[i].B12)%=MOD;
(mul*=a[i].nA12)%=MOD;
(ad*=a[i].nA12)%=MOD;
}
(mul*=a[i].A11)%=MOD;
(ad*=a[i].A11)%=MOD;
(ad+=a[i].B11)%=MOD;
//*
swap(a[i].x,a[i].y);
a[i].y--;
//*/
if(a[i].A22!=0){
change2(rt,1,n,a[i].y+1,n,MOD-a[i].B22);
change1(rt,1,n,a[i].y+1,n,a[i].nA22);
}else{
change4(rt,1,n,a[i].y+1,n,-1);
}
a[i].y++;
swap(a[i].x,a[i].y);
}
i++;
}
if(a[j].c==1){
fro=0;
FLAG=0;
ans[a[j].tim]=ask(rt,1,n,a[j].y,0,ans[a[j].tim]);
if(FLAG){
qinding[a[j].tim]=1;
frog[a[j].tim]=ans[a[j].tim];
}
}
if(a[j].c==2){
fro=0;
if(flag){
qinding[a[j].tim]=1;
frog[a[j].tim]=ts;
}else{
ans[a[j].tim]=(mul*ans[a[j].tim]+ad)%MOD;
}
}
}
}
cdq(MID+1,R,mid+1,r);
tl=l,tr=mid+1;
for(i=l;i<=r;i++){
if((cmpl(a[tl],a)&&tl<=mid)||tr>r){
ta[i]=a[tl++];
}else{
ta[i]=a[tr++];
}
}
memcpy(a+l,ta+l,sizeof(que)*(r-l+1));
}
int main(){
//*/
memset(ans,-1,sizeof(ans));
int i,j,o,x,y;
ine[0]=ine[1]=1;
for(i=2;i<MAXN;i++){
ine[i]=(MOD-MOD/i)*ine[MOD%i]%MOD;
}
n=read();
m=read();
bool hhh=0;
bool hhhh=1;
for(i=1;i<=m;i++){
o=read();
if(o==1){
tot++;
a[tot].tim=i;
a[tot].c=0;
L[i]=read();
R[i]=read();
a[tot].x=L[i];
a[tot].y=R[i];
a[tot].A11=MOD-1;
a[tot].B11=1;
a[tot].A12=(L[i]-R[i]+1+MOD)*ine[R[i]-L[i]+1]%MOD;
a[tot].B12=(R[i]-L[i])*ine[R[i]-L[i]+1]%MOD;
a[tot].A21=(R[i]-L[i]-3+MOD)*ine[R[i]-L[i]+1]%MOD;
a[tot].B21=2*ine[R[i]-L[i]+1]%MOD;
a[tot].A22=(R[i]-L[i]-1+MOD)*ine[R[i]-L[i]+1]%MOD;
a[tot].B22=ine[R[i]-L[i]+1];
a[tot].nA11=mi(a[tot].A11,MOD-2);
a[tot].nA12=mi(a[tot].A12,MOD-2);
a[tot].nA21=mi(a[tot].A21,MOD-2);
a[tot].nA22=mi(a[tot].A22,MOD-2);
tot++;
a[tot]=a[tot-1];
a[tot].c=-1;
swap(a[tot].x,a[tot].y);
a[tot].x++;
}
if(o==2){
hhh=1;
tot++;
a[tot].tim=i;
a[tot].x=read();
a[tot].y=read();
if(a[tot].x==1){
a[tot].x=a[tot].y;
a[tot].c=2;
}else{
a[tot].x--;
a[tot].c=1;
}
ans[i]=1;
}
}
sort(a+1,a+tot+1,cmpl);
cdq(1,m,1,tot);
for(i=1;i<=tot;i++){
if(ans[i]!=-1){
if(qinding[i]){
printf("%lld\n",frog[i]);
}else{
printf("%lld\n",ans[i]);
}
}
}
return 0;
}

/*
5 5
2 3 5
1 3 4
2 1 5
2 5 5
1 3 4

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: