题目描述
如题,已知一个数列有n个数,m次操作,你需要进行下面两种操作:
1. 將某个位置的数平均分给一个区间,不能平均分的留下
2. 求出某个位置的值
输入
第一行两个正整数n、m(1<=n,m<=500,000); n表示数字个数,m表示操作的个数
第二行n个整数,a1,a2,a3,...,an代表数列的初始值 (ai<=10^9)
接下来m行,每行2或4个整数,表示一个操作,具体如下:
操作1:1 p,x,y 将第p个数平均分给区间[x,y] (1<=p,x,y<=n)
操作2:2 p 输出第p个数的值
输入数据过大,建议使用scanf输入
输出
对于每个操作2,输出一个整数
样例输入
5 6 1 2 3 4 8 1 5 1 5 2 1 2 2 2 3 2 4 2 5
样例输出
2
3
4
5
4
解题思路:
很明显区间修改,单点查询
(可以用树状数组和线段树,数据超int)
树状数组:
#include<stdio.h>
#define ll long long
const int maxn = 5e5+5;
int n,m;
ll a[maxn];
ll t[maxn];
void add(int x,ll v){
for (;x<=n;x+=x&-x) t[x]+=v;
}
ll query(int x) {
ll res=0;
for(;x;x-=x&-x) res+=t[x];
return res;
}
int main() {
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) {
scanf("%lld",&a[i]);
add(i,a[i]-a[i-1]);
}
for (int i=1;i<=m;i++) {
int op,p,x,y;
scanf("%d",&op);
if (op==1) {
scanf("%d%d%d",&p,&x,&y);
ll tmp = query(p);
if (tmp < y-x+1) continue;
add(p,-tmp/(y-x+1)*(y-x+1));
add(p+1,tmp/(y-x+1)*(y-x+1));
add(x,tmp/(y-x+1));
add(y+1,-tmp/(y-x+1));
}
else {
scanf("%d",&p);
printf("%lld\n",query(p));
}
}
return 0;
}
线段树
#include<stdio.h>
#define ll long long
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r
const int maxn=1<<20;
int n,m;
ll lz[maxn];
inline void push_down(int rt) {
if (!lz[rt]) return;
lz[rt<<1]+=lz[rt];
lz[rt<<1|1]+=lz[rt];
lz[rt]=0;
}
void build(int rt,int l,int r) {
if (l==r) {
scanf("%lld",&lz[rt]);
return;
}
int m=(l+r)>>1;
build(lson);
build(rson);
}
void update(int rt,int l,int r,int L,int R,ll v) {
if (L<=l&&r<=R) {
lz[rt]+=v;
return;
}
push_down(rt);
int m=(l+r)>>1;
if (L<=m) update(lson,L,R,v);
if (m<R) update(rson,L,R,v);
}
ll query(int rt,int l,int r,int p) {
if (l==r) return lz[rt];
push_down(rt);
int m=(l+r)>>1;
if (p<=m) return query(lson,p);
return query(rson,p);
}
int main() {
scanf("%d%d",&n,&m);
build(1,1,n);
for (int i=1;i<=m;i++) {
int op,p,x,y;
scanf("%d",&op);
if(op==1) {
scanf("%d%d%d",&p,&x,&y);
ll tmp=query(1,1,n,p);
if (tmp<y-x+1) continue;
update(1,1,n,p,p,-tmp/(y-x+1)*(y-x+1));
update(1,1,n,x,y,tmp/(y-x+1));
}
else {
scanf("%d",&p);
printf("%lld\n",query(1,1,n,p));
}
}
return 0;
}