题解:P1438 无聊的数列
题意
给你一个长度为
修改:将
询问:询问序列的第
最后要你输出这个数列每个数的值。
暴力思路
分块,对于散块直接算出等差数列对应的值进行修改,对于整块则是用一个 vector 类型的
询问时就比较暴力了,直接使用循环遍历
Code
#include<bits/stdc++.h>
using namespace std;
int read() {
char ch=getchar();
int r=0,w=1;
while(ch<'0'||ch>'9') w=ch=='-'?-1:w,ch=getchar();
while(ch>='0'&&ch<='9') r=r*10+ch-'0',ch=getchar();
return r*w;
}
void write(long long n){
if(n<0) putchar('-'),n*=-1;
if(n>9) write(n/10);
putchar(n % 10 + '0');
}
//快读快写防止超时
struct jgt{
int x;//开始位置
int y;//初始项
int z;//公差
int cs;//小优化,记录重复次数防止MLE
} cc;
int n,m,s,l,r,k,d;
long long cnt;
long long xl[100001];
int x[401],y[401],fk[100001];
vector<jgt> xg[401];
signed main(){
n=read(),m=read();
for(int i=1;i<=(int)sqrt(n);i++){
cnt++;
x[cnt]=y[cnt-1]+1;
y[cnt]=x[cnt]+(int)sqrt(n)-1;
for(int j=x[cnt];j<=y[cnt];j++){
fk[j]=cnt;
}
}
if(y[cnt]<n){
cnt++;
x[cnt]=y[cnt-1]+1;
y[cnt]=n;
for(int i=x[cnt];i<=y[cnt];i++){
fk[i]=cnt;
}
}
for(int i=1;i<=n;i++){
xl[i]=read();
}
for(int i=1;i<=m;i++){
s=read();
if(s==1){
l=read(),r=read(),k=read(),d=read();
for(int j=l;j<=min(r,y[fk[l]]);j++){
xl[j]+=k+(j-l)*d;
}
if(fk[l]!=fk[r]){
for(int j=x[fk[r]];j<=r;j++){
xl[j]+=k+(j-l)*d;
}
}
for(int j=fk[l]+1;j<fk[r];j++){
if(!xg[j].empty()){
cc=xg[j][xg[j].size()-1];
}
if(l==cc.x&&k==cc.y&&d==cc.z&&!xg[j].empty()){
xg[j][xg[j].size()-1].cs++;
}
//单独处理重复情况
else{
cc.x=l;
cc.y=k;
cc.z=d;
xg[j].push_back(cc);
//更新add数组
}
}
}
else{
k=read();
cnt=xl[k];
for(int j=0;j<xg[fk[k]].size();j++){
cnt+=xg[fk[k]][j].y+(k-xg[fk[k]][j].x)*xg[fk[k]][j].z*(xg[fk[k]][j].cs+1);//原始值加上add数组的值
}
write(cnt);
puts("");
}
}
return 0;
}