题意:
有n个数的一个数组a,有两个操作:
1 l r:查询区间[l,r]内$a[l]*(r-l+1)+a[l+1]*(r-l)+a[l+2]*(r-l-1)+cdots+a[r-1]*2+a[r]$
2 l r:将a[l]修改为r
n<=1e5, a[i]<=1e9
思路:
预处理出前缀和s[i], 则操作1变为查询$s[l]+s[l+1]+..+s[r]-(r-l+1)*s[l-1]$
为防止爆ll(其实也不会爆的)可以在查询操作力就提前减去s[l-1]
坑点来了。。操作2即区间s(l,n)加上r-a[l],由于我们线段树里的一些标记操作,实际上a[i]和s[i]数组并没有变!
所以我们每次需要用s或a数组的时候都要query。。
代码:
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<string> #include<stack> #include<queue> #include<deque> #include<set> #include<vector> #include<map> #include<functional> #define fst first #define sc second #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) #define lson l,mid,root<<1 #define rson mid+1,r,root<<1|1 #define lc root<<1 #define rc root<<1|1 #define lowbit(x) ((x)&(-x)) using namespace std; typedef double db; typedef long double ldb; typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> PI; typedef pair<ll,ll> PLL; const db eps = 1e-6; const int mod = 1e9+7; const int maxn = 1e6+5000; const int maxm = 2e6+100; const int inf = 0x3f3f3f3f; const db pi = acos(-1.0); ll sum[maxn<<2]; ll s[maxn]; ll a[maxn]; int ii; void build(int l, int r, int root){ int mid = l + ((r - l) >> 1);//位运算TMD优先级! if(l == r){ sum[root] = s[l]; return; } build(lson); build(rson); sum[root] = sum[lc]+sum[rc]; } ll addv[maxn << 2]; //将root的信息传到左右节点上 void pushup(int root){ sum[root] = sum[lc] + sum[rc]; return; } void pushdown(int l, int r, int root){ if(addv[root]){ addv[lc] += addv[root]; addv[rc] += addv[root]; int mid = l + ((r-l)>>1); sum[lc] += addv[root]*(mid-l+1); sum[rc] += addv[root]*(r-mid); addv[root] = 0; } return; } void update(int ql, int qr, ll add, int l, int r, int root){ if(ql <= l && qr >= r){ addv[root] += add; sum[root] += add*(r-l+1); return; } pushdown(l, r, root); int mid = l + ((r-l)>>1); if(ql <= mid) update(ql, qr, add, lson); if(qr > mid) update(ql, qr, add, rson); pushup(root); return; } ll query(int ql, int qr, int l, int r, int root){ if(ql==0)return 0; if(ql <= l && qr >= r) return sum[root];//(sum[root]-(ll)((ll)r-l+1)*s[ii-1]); pushdown(l, r, root); int mid = l + ((r-l)>>1); ll ans = 0; if(ql <= mid) ans += query(ql, qr, lson); if(qr > mid) ans += query(ql, qr, rson); return ans; } int main() { int n, q; scanf("%d %d", &n, &q); for(int i =1; i <= n ; i++){ scanf("%lld", &a[i]); }s[0] = 0; mem(s, 0); for(int i = 1; i <= n; i++){ s[i] = a[i]+s[i-1]; } mem(addv, 0); mem(sum, 0); build(1, n, 1); while(q--){ int c,l,r; scanf("%d %d %d", &c, &l, &r); if(c==1){ ii = l; printf("%lld ", query(l, r, 1, n, 1) -(r-l+1)*query(l-1,l-1,1,n,1)); } else if(c==2){ ll tmp = (ll)r-(query(l, l, 1, n, 1) -query(l-1, l-1, 1, n, 1)); update(l, n, tmp, 1, n, 1); }A } return 0; } /* 5 10 1000000000 1000000000 1000000000 1000000000 1000000000 1 2 4 2 1 0 1 2 4 */