zoukankan      html  css  js  c++  java
  • bzoj4397【Usaco2015 Dec】Breed Counting(前缀和、树状数组)

    题目描述

    Farmer John's N cows, conveniently numbered 1…N, are all standing in a row (they seem to do so often that it now takes very little prompting from Farmer John to line them up). Each cow has a breed ID: 1 for Holsteins, 2 for Guernseys, and 3 for Jerseys. Farmer John would like your help counting the number of cows of each breed that lie within certain intervals of the ordering.

    输入

    The first line of input contains N and Q (1≤N≤100,000, 1≤Q≤100,000).

    The next N lines contain an integer that is either 1, 2, or 3, giving the breed ID of a single cow in the ordering.

    The next Q lines describe a query in the form of two integers a,b (a≤b).

    输出

    For each of the Q queries (a,b), print a line containing three numbers: the number of cows numbered a…b that are Holsteins (breed 1), Guernseys (breed 2), and Jerseys (breed 3).

    样例输入

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

    样例输出

    3 2 1
    1 0 0
    2 0 1
    
      题目的意思就是给你n个牛槽的位置(编号从1到n),q是查询次数,每个牛槽里有一只奶牛,奶牛有三个品种(分别为1,2,3),告诉你每个牛槽中奶牛的种类。
    给你q个查询的区间,让你输出每个查询区间内三种奶牛分别有多少头。
      这个题我写了两种解法,一种是前缀和数组(a[i]表示从1到i一共有多少头X品种牛),还有一种解法就是写树状数组。但是从运行时间上来看,肯定是前缀和要比树状数组要快。
    前缀和数组代码如下:
     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 int sum[3][100050];
     4 int main()
     5 {
     6     int n,q;
     7     //freopen("de.txt","r",stdin);
     8     while (~scanf("%d%d",&n,&q))
     9     {
    10         memset(sum,0,sizeof sum);
    11         for (int i=1;i<=n;++i)
    12         {
    13             for (int j=0;j<3;++j)
    14             sum[j][i]=sum[j][i-1];
    15             int x;
    16             scanf("%d",&x);
    17             sum[x-1][i]++;
    18         }
    19         for (int i=0;i<q;++i)
    20         {
    21             int x,y;
    22             scanf("%d%d",&x,&y);
    23             printf("%d %d %d
    ",sum[0][y]-sum[0][x-1],sum[1][y]-sum[1][x-1],sum[2][y]-sum[2][x-1]);
    24         }
    25     }
    26  
    27 }
       Time:100 ms
        Memory:2868 kb


    树状数组代码如下:

     1 #include <iostream>
     2 #include <cstring>
     3 #include <cmath>
     4 #include <cstdio>
     5 #include <algorithm>
     6 #include <string>
     7 using namespace std;
     8 #define maxn 111111
     9 int sum[maxn<<2][3],sum2[maxn<<2],sum3[maxn<<2];
    10 void pushup (int rt,int num)
    11 {
    12     sum[rt][num]=sum[rt<<1][num]+sum[rt<<1|1][num];
    13 }
    14  
    15 void update (int p,int l,int r,int rt,int num)
    16 {
    17     if (l==r)
    18     {
    19         sum[rt][num]++;
    20         return;
    21     }
    22     int m=(l+r)>>1;
    23     if (p<=m)
    24     update(p,l,m,rt<<1,num);
    25     else
    26     update(p,m+1,r,rt<<1|1,num);
    27     pushup(rt,num);
    28 }
    29 int query (int ll,int rr,int l,int r,int rt,int num)
    30 {
    31     if (ll<=l&&rr>=r)
    32     return sum[rt][num];
    33  
    34     int ret=0;
    35     int m=(l+r)>>1;
    36  
    37     if (ll<=m)
    38     ret+=query(ll,rr,l,m,rt<<1,num);
    39     if (rr>m)
    40     ret+=query(ll,rr,m+1,r,rt<<1|1,num);
    41     return ret;
    42 }
    43 int main()
    44 {
    45     int n,q;
    46     //freopen("de.txt","r",stdin);
    47     while (~scanf("%d%d",&n,&q))
    48     {
    49         memset(sum,0,sizeof sum);
    50         for (int i=1;i<=n;++i)
    51         {
    52             int x;
    53             scanf("%d",&x);
    54             update(i,1,n,1,x-1);
    55         }
    56         for (int i=0;i<q;++i)
    57         {
    58             int x,y;
    59             scanf("%d%d",&x,&y);
    60             printf("%d ",query(x,y,1,n,1,0));
    61             printf("%d ",query(x,y,1,n,1,1));
    62             printf("%d
    ",query(x,y,1,n,1,2));
    63         }
    64     }
    65     return 0;
    66 }
    67     Time:360 ms
    68     Memory:10376 kb

    PS:这个树状数组的模板是我hdu1166这个题的模板改的。

     
  • 相关阅读:
    每日一题_191101
    阿基米德三角形(交互式学件)
    2018四川高考数学(全国卷3)理科21题以泰勒公式为命题背景(同时深挖去年高考题)和它的另类解法的瞎谈
    给老谢画的图(平面几何中的动点与最值问题)
    2018四川高考文科21题
    数学解题的思维过程
    Qt Creator 模块QtSql
    QT Creator快捷键不能用
    QT 随机数
    C++ 4 种具有更 为准确语义的新强制转换类型
  • 原文地址:https://www.cnblogs.com/agenthtb/p/5759528.html
Copyright © 2011-2022 走看看