• bzoj 3236: [Ahoi2013]作业(缺线段树)


    3236: [Ahoi2013]作业

    Time Limit: 100 Sec  Memory Limit: 512 MB
    Submit: 1744  Solved: 702
    [Submit][Status][Discuss]

    Description

    Input

    Output

    Sample Input

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

    Sample Output

    2 2
    1 1
    3 2
    2 1

    HINT

    N=100000,M=1000000

    Source

    By wangyisong1996加强数据

    思路:莫队套权值树状数组。

    错因:数组开小了。

    莫队套树状数组:

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 1000001
    using namespace std;
    int n,m,S,ans;
    int num[MAXN],sum[MAXN],c[2][MAXN];
    struct nond{
        int l,r,a,b;
        int id,pos,ans,sum;
    }edge[MAXN];
    int cmp(nond a,nond b){
        if(a.pos==b.pos)    return a.r<b.r;
        else return a.pos<b.pos;
    }
    int cmp1(nond a,nond b){
        return a.id<b.id;
    }
    int lowbit(int x){
        return x&(-x);
    }
    void change(int k,int w,int h){
        while(k<=n){
            c[h][k]+=w;
            k+=lowbit(k);        
        }
    }
    int query(int k,int h){
        int tot=0;
        while(k){
            tot+=c[h][k];
            k-=lowbit(k);
        }
        return tot;
    }
    void up(int x,int k){
        sum[num[x]]+=k;
        change(num[x],k,1);
        if(k==1&&sum[num[x]]==1)    change(num[x],k,0);
        else if(k==-1&&sum[num[x]]==0)    change(num[x],k,0);
    }
    void mode(){
        int l=1,r=0;
        for(int i=1;i<=m;i++){
            while(l<edge[i].l) up(l++,-1);
            while(l>edge[i].l) up(--l,1);
            while(r<edge[i].r) up(++r,1);
            while(r>edge[i].r) up(r--,-1);
            edge[i].sum=query(edge[i].b,0)-query(edge[i].a-1,0);
            edge[i].ans=query(edge[i].b,1)-query(edge[i].a-1,1);
        }
    }
    int main(){
        freopen("ahoi2013_homework.in","r",stdin);
        freopen("ahoi2013_homework.out","w",stdout);
        scanf("%d%d",&n,&m);
        S=sqrt(n);
        for(int i=1;i<=n;i++)
            scanf("%d",&num[i]);
        for(int i=1;i<=m;i++){
            scanf("%d%d%d%d",&edge[i].l,&edge[i].r,&edge[i].a,&edge[i].b);
            edge[i].id=i;
            edge[i].pos=(edge[i].l-1)/S+1;
        }
        sort(edge+1,edge+1+m,cmp);
        mode();
        sort(edge+1,edge+1+m,cmp1);
        for(int i=1;i<=m;i++)
            cout<<edge[i].ans<<" "<<edge[i].sum<<endl;
    }

    莫队套线段树:

    细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。 雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。
  • 相关阅读:
    java抽象类怎么实例化了及C++中抽象类的构造函数
    树及其遍历
    C++中类的多态与虚函数的使用
    C++中#if #ifdef 的作用
    用链表实现两大数相乘
    C++中的链表类的设计
    IPicture总结
    c++标准库中,含有链表的类list
    TCP/IP、Http的区别
    C语言单链表实现19个功能完全详解
  • 原文地址:https://www.cnblogs.com/cangT-Tlan/p/7496571.html
Copyright © 2020-2023  润新知