题解:[ABC256Ex] I like Query Problem
可以纯分块。
直接分块肯定会炸,所以套用一点势能线段树的思想,在块内所有值相等时把它当成一个点来维护,对应代码中的
对于操作
对于操作
询问时跟普通分块一样直接统计答案即可。
需要注意的是修改分块由于要保证
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=5e5+1;
int n,q,opt,l,r,s;
int xl[N];
int x[N],y[N],fk[N],ans[N],maxx[N],minn[N],tp[N];
signed main(){
cin>>n>>q;
int cnt=sqrt(n);
for(int i=1;i<=cnt;i++){
x[i]=y[i-1]+1;
y[i]=x[i]+cnt-1;
}
if(y[cnt]<n){
cnt++;
x[cnt]=y[cnt-1]+1;
y[cnt]=n;
}
for(int i=1;i<=n;i++){
cin>>xl[i];
}
for(int i=1;i<=n;i++){
tp[i]=-1,minn[i]=INT_MAX;
for(int j=x[i];j<=y[i];j++){
fk[j]=i;
ans[i]+=xl[j];
maxx[i]=max(maxx[i],xl[j]);
minn[i]=min(minn[i],xl[j]);
}
}
for(int i=1;i<=q;i++){
cin>>opt>>l>>r;
if(opt==1){
cin>>s;
if(tp[fk[l]]){
if(tp[fk[l]]!=-1){
for(int j=x[fk[l]];j<=y[fk[l]];j++){
xl[j]=tp[fk[l]];
}
}
for(int j=l;j<=min(r,y[fk[l]]);j++){
ans[fk[l]]-=xl[j];
xl[j]/=s;
ans[fk[l]]+=xl[j];
}
maxx[fk[l]]=0,minn[fk[l]]=INT_MAX;
for(int j=x[fk[l]];j<=y[fk[l]];j++){
maxx[fk[l]]=max(maxx[fk[l]],xl[j]);
minn[fk[l]]=min(minn[fk[l]],xl[j]);
}
if(maxx[fk[l]]==minn[fk[l]]){
tp[fk[l]]=xl[l];
}
else{
tp[fk[l]]=-1;
}
}
if(fk[l]!=fk[r]){
if(tp[fk[r]]){
if(tp[fk[r]]!=-1){
for(int j=x[fk[r]];j<=y[fk[r]];j++){
xl[j]=tp[fk[r]];
}
}
for(int j=x[fk[r]];j<=r;j++){
ans[fk[r]]-=xl[j];
xl[j]/=s;
ans[fk[r]]+=xl[j];
}
maxx[fk[r]]=0,minn[fk[r]]=INT_MAX;
for(int j=x[fk[r]];j<=y[fk[r]];j++){
maxx[fk[r]]=max(maxx[fk[r]],xl[j]);
minn[fk[r]]=min(minn[fk[r]],xl[j]);
}
if(maxx[fk[r]]==minn[fk[r]]){
tp[fk[r]]=xl[r];
}
else{
tp[fk[r]]=-1;
}
}
}
for(int j=fk[l]+1;j<fk[r];j++){
maxx[j]/=s;
minn[j]/=s;
if(tp[j]!=-1){
if(tp[j]){
tp[j]/=s;
ans[j]=(y[j]-x[j]+1)*tp[j];
}
}
else{
if(maxx[j]==minn[j]){
tp[j]=maxx[j];
ans[j]=(y[j]-x[j]+1)*tp[j];
}
else{
for(int k=x[j];k<=y[j];k++){
ans[j]-=xl[k];
xl[k]/=s;
ans[j]+=xl[k];
}
}
}
}
}
if(opt==2){
cin>>s;
if(tp[fk[l]]!=-1){
for(int j=x[fk[l]];j<=y[fk[l]];j++){
xl[j]=tp[fk[l]];
}
}
for(int j=l;j<=min(r,y[fk[l]]);j++){
ans[fk[l]]-=xl[j];
xl[j]=s;
ans[fk[l]]+=xl[j];
}
maxx[fk[l]]=minn[fk[l]]=s;
for(int j=x[fk[l]];j<=y[fk[l]];j++){
maxx[fk[l]]=max(maxx[fk[l]],xl[j]);
minn[fk[l]]=min(minn[fk[l]],xl[j]);
}
if(maxx[fk[l]]==minn[fk[l]]){
tp[fk[l]]=xl[l];
}
else{
tp[fk[l]]=-1;
}
if(fk[l]!=fk[r]){
if(tp[fk[r]]!=-1){
for(int j=x[fk[r]];j<=y[fk[r]];j++){
xl[j]=tp[fk[r]];
}
}
for(int j=x[fk[r]];j<=r;j++){
ans[fk[r]]-=xl[j];
xl[j]=s;
ans[fk[r]]+=xl[j];
}
maxx[fk[r]]=minn[fk[r]]=s;
for(int j=x[fk[r]];j<=y[fk[r]];j++){
maxx[fk[r]]=max(maxx[fk[r]],xl[j]);
minn[fk[r]]=min(minn[fk[r]],xl[j]);
}
if(maxx[fk[r]]==minn[fk[r]]){
tp[fk[r]]=xl[r];
}
else{
tp[fk[r]]=-1;
}
}
for(int j=fk[l]+1;j<fk[r];j++){
tp[j]=s;
ans[j]=(y[j]-x[j]+1)*s;
}
}
if(opt==3){
int cnt=0;
for(int j=l;j<=min(r,y[fk[l]]);j++){
if(tp[fk[l]]!=-1){
cnt+=tp[fk[l]];
}
else{
cnt+=xl[j];
}
}
if(fk[l]!=fk[r]){
for(int j=x[fk[r]];j<=r;j++){
if(tp[fk[r]]!=-1){
cnt+=tp[fk[r]];
}
else{
cnt+=xl[j];
}
}
}
for(int j=fk[l]+1;j<fk[r];j++){
cnt+=ans[j];
}
cout<<cnt<<endl;
}
}
return 0;
}