• [BZOJ 3236][Ahoi2013]作业(莫队+树状数组)


    Description

    传送门

    Solution

    莫队

    一开始维护数的个数和数值的个数都用了树状数组,果断超时QAQ

    把数的个数改成了按权值分块

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #define N 100005
    #define M 1000005
    using namespace std;
    int n,m,block,x[N],pos[N],ans1[M],ans2[M],num[N];
    int g1[N];
    struct Node
    {
        int l,r,a,b,id;
        bool operator < (const Node& t) const
        {
            if(pos[l]==pos[t.l])
            return pos[r]<pos[t.r];
            else return pos[l]<pos[t.l];
        }
    }q[M];
    struct BIT
    {
        int c[N];
        inline int lowbit(int x){return x&-x;}
        void add(int pos,int x)
        {
            while(pos<=n)
            c[pos]+=x,pos+=lowbit(pos);
        }
        int query(int pos)
        {
            int res=0;
            while(pos>0)res+=c[pos],pos-=lowbit(pos);
            return res;
        }
    }t2;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    void change(int t,int f)
    {
        g1[pos[x[t]]]+=f;//t1.add(x[t],f);
        if(num[x[t]]==0&&f==1)t2.add(x[t],1);
        else if(num[x[t]]==1&&f==-1)t2.add(x[t],-1);
        num[x[t]]+=f;
    }
    void query(int id,int a,int b)
    {
        if(pos[a]==pos[b])
        {
            for(int i=a;i<=b;i++)
            ans1[id]+=num[i];
            return;
        }
        for(int i=a;i<=pos[a]*block;i++)ans1[id]+=num[i];
        for(int i=pos[a]+1;i<=pos[b]-1;i++)ans1[id]+=g1[i];
        for(int i=b;i>(pos[b]-1)*block;i--)ans1[id]+=num[i];
    }
    int main()
    {
        n=read(),m=read();
        block=(int)sqrt(n);
        for(int i=1;i<=n;i++)
        x[i]=read(),pos[i]=(i-1)/block+1;
        for(int i=1;i<=m;i++)
        q[i].l=read(),q[i].r=read(),q[i].a=read(),q[i].b=read(),q[i].id=i;
        sort(q+1,q+1+m);
        int l=1,r=0;
        for(int i=1;i<=m;i++)
        {
            while(l<q[i].l)change(l++,-1);
            while(l>q[i].l)change(--l,1);
            while(r>q[i].r)change(r--,-1);
            while(r<q[i].r)change(++r,1);
            if(q[i].a<0)q[i].a=1;
            query(q[i].id,q[i].a,q[i].b);
            ans2[q[i].id]=t2.query(q[i].b)-t2.query(q[i].a-1);
        }
        for(int i=1;i<=m;i++)
        printf("%d %d
    ",ans1[i],ans2[i]);
        return 0;
    }
  • 相关阅读:
    计科4班曾祥刚2016024290
    线程:子线程先循环十次,主线程在循环20次,再子线程循环十次,主线程循环20次,如此循环50次
    java经典程序(11-20)
    java经典程序(1-10)
    String,File和xml
    自写一个双向链表
    i love my girl
    javamail发邮件
    Java反射机制(创建Class对象的三种方式)
    java基础面试题
  • 原文地址:https://www.cnblogs.com/Zars19/p/6970138.html
Copyright © 2020-2023  润新知