zoukankan      html  css  js  c++  java
  • bzoj2989&4170: 数列

    Description

    给定一个长度为n的正整数数列a[i]。
    定义2个位置的graze值为两者位置差与数值差的和,即graze(x,y)=|x-y|+|a[x]-a[y]|。
    2种操作(k都是正整数):
    1.Modify x k:将第x个数的值修改为k。
    2.Query x k:询问有几个i满足graze(x,i)<=k。因为可持久化数据结构的流行,询问不仅要考虑当前数列,还要考虑任意历史版本,即统计任意位置上出现过的任意数值当前的a[x]的graze值<=k的对数。(某位置多次修改为同样的数值,按多次统计)

    Input

    第1行两个整数n,q。分别表示数列长度和操作数。
    第2行n个正整数,代表初始数列。
    第3--q+2行每行一个操作。

    Output

        对于每次询问操作,输出一个非负整数表示答案。

    Sample Input

    3 5
    2 4 3
    Query 2 2
    Modify 1 3
    Query 2 2
    Modify 1 2
    Query 1 1

    Sample Output

    2
    3
    3

    HINT

    N<=60000 修改操作数<=40000 询问<=10000 Max{a[i]}含修改<=100000

    思路:考场上打了个暴力,竟然有70分....

    CDQ分治,先把坐标(x,y)转换成(x-y,x+y),然后就是正放着的矩形了,询问就是矩形中点的个数。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=60010,maxm=260010,maxq=500010;
    int n,q,a[maxn],ans[maxq],cnt,lim;
    bool que[maxq];char op[10];
    struct node{int num,id,op,x,y,t;}li[maxq],tmp[maxq];
    struct Bit{
        int val[maxq]; 
        void change(int x,int v){for (;x<=lim;x+=x&-x) val[x]+=v;}
        int query(int x){int res=0;for (;x;x-=x&-x) res+=val[x];return res;}
    }T;
     
    void add(int op,int id,int x,int y,int k){
        int xx=x-y,yy=x+y;
        if (!op) lim=max(lim,xx),lim=max(lim,yy),li[++cnt]=(node){cnt,id,op,xx,yy,0};
        else{
            int x1=xx-k,y1=yy-k,x2=xx+k,y2=yy+k;
            if (y1>0) li[++cnt]=(node){cnt,id,op,x1-1,y1-1,1};
            li[++cnt]=(node){cnt,id,op,x1-1,y2,-1};
            if (y1>0) li[++cnt]=(node){cnt,id,op,x2,y1-1,-1};
            li[++cnt]=(node){cnt,id,op,x2,y2,1};
            lim=max(lim,x2),lim=max(lim,y2);
        }
    }
     
    void solve(int l,int r){
        if (l==r) return;
        int mid=(l+r)>>1;
        solve(l,mid),solve(mid+1,r);
        for (int i=l,a=l,b=mid+1;i<=r;i++){
            node p;
            if (a<=mid&&(b>r||li[a].x<=li[b].x)) p=li[a++];
            else p=li[b++];
            if (p.num<=mid&&!p.op) T.change(p.y,1);
            if (p.num>mid&&p.op) ans[p.id]+=T.query(p.y)*p.t;
            tmp[i]=p;
        }
        for (int i=l;i<=r;i++) li[i]=tmp[i];
        for (int i=l;i<=r;i++) if (li[i].num<=mid&&!li[i].op) T.change(li[i].y,-1);
    }
     
    int main(){
        scanf("%d%d",&n,&q);
        for (int i=1;i<=n;i++) scanf("%d",&a[i]),add(0,i,i,a[i],0);
        for (int i=n+1,x,k;i<=n+q;i++){
            scanf("%s%d%d",op,&x,&k);
            if (op[0]=='M') a[x]=k,add(0,i,x,a[x],0);
            else que[i]=1,add(1,i,x,a[x],k);
        }
        n+=q,lim++,solve(1,cnt);
        for (int i=1;i<=cnt;i++) if (que[i]) printf("%d
    ",ans[i]);
        return 0;
    }


  • 相关阅读:
    Java异常处理和设计
    一次qps测试实践
    Alternate Task UVA
    Just Another Problem UVA
    Lattice Point or Not UVA
    Play with Floor and Ceil UVA
    Exploring Pyramids UVALive
    Cheerleaders UVA
    Triangle Counting UVA
    Square Numbers UVA
  • 原文地址:https://www.cnblogs.com/thythy/p/5493585.html
Copyright © 2011-2022 走看看