• Galahad


    Galahad

    魔女要测试骑士的能力,要求他维护一个长度为 n的序列,每次要询问一个区间的和。

    但是魔女觉得太简单了,骑士能轻松记住 个数作为前缀和。

    于是,魔女要求他回答一个区间的和,但如果某一个数在这个区间出现了多次,这个数只能被计算一次。

    输入描述:

    第一行两个整数 n,m表示数列长度和询问个数。

    第二行 n个整数,第i个整数为(a_i(1le n,qle500 000)),表示序列中的第i项。

    接下来m行,每行两个整数l,r表示询问的区间。

    输出描述:

    输出 m行,每行一个整数表示这次询问的答案。
    示例1

    5 3
    1 3 3 2 1
    1 5
    1 3
    2 4
    

    输出

    6
    4
    5
    

    区间和问题
    先离线查询,按照询问右端点从小大大排序,令数组(b)初始值=0,last[x]记录x上一次出现的位置,从1开始遍历(a_i),对b在区间([last[a_i], i])(a_i), 若某个询问是([l, r]),则当r==i时,此次询问的答案为(b[l])
    (因为对于某个询问,r之前的数都被遍历过了,如果([1,r])(a_i)=x有多个重复,(b[l])只加了一次x,如果(a_i)=y没有重复,则区间([1,l])都加了y,所以(b[l])加了y)
    数组b区间修改和单点查询,用树状数组维护差分即可,复杂度(O(mlogm+nlogn))

    #include<bits/stdc++.h>
    using namespace std;
    char buf[1<<17],*L=buf,*R=buf;
    #define gc() L==R&&(R=(L=buf)+fread(buf,1,1<<17,stdin),L==R)?EOF:*L++;
    template<typename T>
    inline void read(T&x) {x=0;
        char ch=gc();
        while (ch<'0'||ch>'9')ch=gc();
        while (ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-48,ch=gc();
    }
    #define Init(arr,val) memset(arr,val,sizeof(arr))
    #define lowbit(x) ((x)&(-x))
    typedef long long ll;
    const int inf=0x3f3f3f3f,MAXN=5e5+8;
    int n,m,a[MAXN],last[MAXN];
    ll d[MAXN],ans[MAXN];
    void add(int pos,int val){
        while(pos<=n){
            d[pos]+=val;
            pos+=lowbit(pos);
        }
    }
    ll sum(int pos){
        ll res=0;
        while(pos){
            res+=d[pos];
            pos-=lowbit(pos);
        }
        return res;
    }
    struct node{
        int x,y,pos;
    }k[MAXN];
    bool cmp(const node&a,const node&b){
        return a.y<b.y;
    }
    int main(){
        read(n),read(m);
        for(int i=1;i<=n;++i)read(a[i]);
        for(int i=0;i<m;++i){
            read(k[i].x),read(k[i].y);
            k[i].pos=i;
        }
        sort(k,k+m,cmp);
        for(int i=1,j=0;i<=n&&j<m;++i){
            add(last[a[i]]+1,a[i]);
            add(i+1,-a[i]);
            last[a[i]]=i;
            while(k[j].y==i){
                ans[k[j].pos]=sum(k[j].x);
                j++;
            }
        }
        for(int i=0;i<m;++i)printf("%lld
    ",ans[i]);
        return 0;
    }
    
  • 相关阅读:
    ORA-32004 的错误处理
    告警日志
    ORACLE 归档日志打开关闭方法
    oracle归档日志配置查询
    教你如何阅读Oracle数据库官方文档
    使用Oracle安装账户登录数据库
    poj 2186 (强连通缩点)
    poj 2516 (费用流)
    STL集合容器set按照由小到大或者由大到小的顺序存放元素
    Android项目 手机安全卫士(代码最全,注释最详细)之十二 设置中心的界面
  • 原文地址:https://www.cnblogs.com/foursmonth/p/14145530.html
Copyright © 2020-2023  润新知