swjtuoj 2389 The Trip On Abandoned Railway

来源:互联网 发布:java 并发和线程 编辑:程序博客网 时间:2024/06/11 09:56

题目链接:The Trip On Abandoned Railway

题目大意:给你一个长度为n的数列和一个公差d,然后m个操作,操作分为两种,第一种操作有一个x和y,代表从x开始的每个数按照等差数列开始加,x这个位置加上y,x+1这个位置加上y+d,x+2这个位置加上y+2*d,依次递推;第二种操作有一个x,代表把这个位置的数模1e9+7后输出,并且这个位置变成零

题目思路:数据范围很大,所以考虑使用线段树,考虑每次更新x到n加上y,然后i从x+1到n,每次更新i到n加上d,但是这样的复杂度会超时,因为每次更新的时候会多一个n,然后西瓜给了个前缀和的做法,线段树和树状数组同时用,每次进行操作1的时候,用树状数组将这个点更新为y(用于处理首项和的问题),然后用线段树把整个【x+1,n】的值全部加上1(用于判断有多少个d的前缀和),然后操作二的时候,直接用树状数组统计一下x之前所有的和,实际上就是累加了多少个首项,然后用线段树取【1,x】里面的1然后乘以一个d就好了,最后加上a[i]就好,最后a[i]要减去这个值,大概做法就这样(前排膜西瓜巨的神做法)

#include <bits/stdc++.h>#define eps 1e-6using namespace std;typedef long long ll;typedef double db;const int maxn = 1e5 + 5;const int mod = 1e9 + 7;const int INF = 1e8 + 5;const ll inf = 1e15 + 8;ll a[maxn];ll c[maxn], n, d;int lowbit(int x) {    return x & -x;}void up(int x, ll d) {    while (x < maxn) {        c[x] += d;        c[x] %= mod;        x += lowbit(x);    }}ll getsum(int x) {    int ans = 0;    while (x) {        ans += c[x];        ans %= mod;        x -= lowbit(x);    }    return ans;}struct TREE {    ll l, r, val, lazy;    void fun(ll tmp) {        lazy += tmp;        val += (r - l + 1) * tmp;    }} tre[maxn*4];void PushDown(int id) {    if (tre[id].lazy) {        tre[id<<1].fun(tre[id].lazy);        tre[id<<1|1].fun(tre[id].lazy);        tre[id].lazy = 0;    }}void PushUp(int id) {    tre[id].val = tre[id<<1].val + tre[id<<1|1].val;}void build(int id, int l, int r) {    tre[id].l = l, tre[id].r = r, tre[id].lazy = 0;    if (l == r) tre[id].val = 0;    else {        int mid = (l + r) >> 1;        build(id<<1, l, mid);        build(id<<1|1, mid+1, r);        PushUp(id);    }}void update(int id, int st, int ed, int val) {    int l = tre[id].l, r = tre[id].r;    if (st <= l && ed >= r) tre[id].fun(val);    else {        PushDown(id);        int mid = l + r >> 1;        if (st <= mid) update(id<<1, st, ed, val);        if (ed > mid) update(id<<1|1, st, ed, val);        PushUp(id);    }}ll query(int id, int st, int ed) {    int l = tre[id].l, r = tre[id].r;    if (st <= l && ed >= r) return tre[id].val;    else {        PushDown(id);        int mid = l + r >> 1;        ll sum1 = 0, sum2 = 0;        if (st <= mid) sum1 = query(id<<1, st, ed);        if (ed > mid) sum2 = query(id<<1|1, st, ed);        PushUp(id);        return sum1 + sum2;    }}void solve() {    int m;    scanf("%lld%d%lld",&n,&m,&d);    for (int i = 1; i <= n; i++) scanf("%lld", a + i);    memset(c, 0, sizeof(c));    build(1, 1, n);    ll tot = 0;    while (m--) {        int op, x, y; scanf("%d%d", &op, &x);        if (op == 1) {            scanf("%d", &y);            up(x, y);            update(1, x + 1, n , 1);        }        else {            ll tmp = getsum(x) + query(1, 1, x) * d + a[x];            printf("%lld\n", tmp % mod);            a[x] -= tmp;            //printf("a[x] = %d\n",a[x]);        }    }}int main(){    freopen("in.txt", "r", stdin);    int t = 1;    scanf("%d",&t);    while (t--) {        solve();    }    return 0;}
原创粉丝点击