2018 icpc徐州赛区网络赛 H题

https://nanti.jisuanke.com/t/31460

这题用线段树和树状数组都能过

大致思路就是维护两个线段树,一个是存每个元素(下标为i)的区间和,另一个存每个元素乘n-i+1的区间和。

询问时只需用第二个线段树的区间和减去第一个线段树的区间和的(n-left)倍数就行了

WA原因:int改成longlong一定要检查一下各函数返回值和scanf中是否也改成了longlong啊。。

线段树版本:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#define MAXN 100006
#define inf 0x3f3f3f3f
using namespace std;
typedef unsigned long long ll;
int n,m,t;
struct node1{
    int l,r;//区间[l,r]
    ll add;//区间的延时标记
    ll sum;//区间和
}tree1[MAXN*4];

struct node2{
    int l,r;
    ll add;
    ll sum;
}tree2[MAXN*4];

void pushup1(int index){
    tree1[index].sum = tree1[index<<1].sum+tree1[index<<1|1].sum;
}
void pushup2(int index){
    tree2[index].sum = tree2[index<<1].sum+tree2[index<<1|1].sum;
}
void pushdown1(int index){
    if(tree1[index].add){
        tree1[index<<1].sum = (tree1[index<<1].r-tree1[index<<1].l+1)*tree1[index].add;
        tree1[index<<1|1].sum = (tree1[index<<1|1].r-tree1[index<<1|1].l+1)*tree1[index].add;
        tree1[index<<1].add = tree1[index].add;
        tree1[index<<1|1].add = tree1[index].add;
        tree1[index].add = 0;
    }
}
void pushdown2(int index){
    if(tree2[index].add){
        tree2[index<<1].sum = (tree2[index<<1].r-tree2[index<<1].l+1)*tree2[index].add;
        tree2[index<<1|1].sum = (tree2[index<<1|1].r-tree2[index<<1|1].l+1)*tree2[index].add;
        tree2[index<<1].add = tree2[index].add;
        tree2[index<<1|1].add = tree2[index].add;
        tree2[index].add = 0;
    }
}
void build(int l,int r,int index){
    tree1[index].l=tree2[index].l=l;
    tree1[index].r=tree2[index].r=r;
    tree1[index].add=tree2[index].add=0;
    if(l==r){
        scanf("%lld",&tree2[index].sum);
        tree1[index].sum=(n-t)*tree2[index].sum;
        //cout<<"&"<<tree1[index].sum<<endl;
        t++;
        return;
    }
    int mid = (l+r)>>1;
    build(l,mid,index<<1);
    build(mid+1,r,index<<1|1);
    pushup1(index);
    pushup2(index);
}
void updata1(int l,int r,int index,ll val){
    if(l <= tree1[index].l && r >= tree1[index].r){
		tree1[index].sum = (tree1[index].r-tree1[index].l+1)*val;
        tree1[index].add = val;
        return ;
    }
    pushdown1(index);
    int mid = (tree1[index].l+tree1[index].r)>>1;
    if(l <= mid){
        updata1(l,r,index<<1,val);
    }
    if(r > mid){
        updata1(l,r,index<<1|1,val);
    }
    pushup1(index);
}
void updata2(int l,int r,int index,ll val){
    if(l <= tree2[index].l && r >= tree2[index].r){
		tree2[index].sum = (tree2[index].r-tree2[index].l+1)*val;
        tree2[index].add = val;
        return ;
    }
    pushdown2(index);
    int mid = (tree2[index].l+tree2[index].r)>>1;
    if(l <= mid){
        updata2(l,r,index<<1,val);
    }
    if(r > mid){
        updata2(l,r,index<<1|1,val);
    }
    pushup2(index);
}
ll query1(int l,int r,int index){
    if(l <= tree1[index].l && r >= tree1[index].r){
        return tree1[index].sum;
    }
    //cout<<"&"<<tree1[index].sum<<endl;
    pushdown1(index);
    int mid=(tree1[index].l+tree1[index].r)>>1;
    ll ans=0;
    if(l <= mid){
        ans += query1(l,r,index<<1);
    }
    if(r > mid){
        ans += query1(l,r,index<<1|1);
    }
    return ans;
}
ll query2(int l,int r,int index){
    if(l <= tree2[index].l && r >= tree2[index].r){
        return tree2[index].sum;
    }
    pushdown2(index);
    int mid=(tree2[index].l+tree2[index].r)>>1;
    ll ans=0;
    if(l <= mid){
        ans += query2(l,r,index<<1);
    }
    if(r > mid){
        ans += query2(l,r,index<<1|1);
    }
    return ans;
}
int main()
{
    int q,x,y;
    ll z;
    while(~scanf("%d%d",&n,&m)){
        build(1,n,1);
        while(m--){
            t=1;
            scanf("%d",&q);
            if(q == 1){
                scanf("%d %d",&x,&y);
                ll q1=query1(x,y,1);
                ll q2=query2(x,y,1);
                if(n==y)
                    cout<<q1<<endl;
                else
                	cout<<q1-(n-y)*q2<<endl;
            }
            else{
                scanf("%d %lld",&x,&z);
                updata1(x,x,1,(n-x+1)*z);
                updata2(x,x,1,z);
            }
        }
    }
    return 0;
}

树状数组版本:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long ll;
const int N=1e5+5;
int n,m;
ll a[N],b[N];
ll lowbit(ll x){
    return (-x)&x;
}
void add1(ll pos,ll x){
    while(pos<=n){
        a[pos]+=x;
        pos+=lowbit(pos);
    }
}
void add2(ll pos,ll x){
    while(pos<=n){
        b[pos]+=x;
        pos+=lowbit(pos);
    }
}

ll query1(ll pos){
    ll res=0;
    while(pos>0){
        res+=a[pos];
        pos-=lowbit(pos);
    }
    return res;
}
ll query2(ll pos){
    ll res=0;
    while(pos>0){
        res+=b[pos];
        pos-=lowbit(pos);
    }
    return res;
}

void input(){
    ll x;
    for(int i=1;i<=n;i++){
        scanf("%lld",&x);
        add2(i,x);
        add1(i,x*(n-i+1));
    }
}

int main(){
    scanf("%d%d",&n,&m);
    input();
    int f;
    ll x,y;
    for(int i=1;i<=m;i++){
        scanf("%d%lld%lld",&f,&x,&y);
        if(f==2){
        	ll pre=query2(x)-query2(x-1);
        	add2(x,y-pre);
        	add1(x,(y-pre)*(n-x+1));
        }
        else if(f==1){
            ll s2=query2(y)-query2(x-1);
            ll s1=query1(y)-query1(x-1);
            cout<<s1-(n-y)*s2<<endl;
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40038776/article/details/82561149