zoukankan      html  css  js  c++  java
  • bzoj5016 [Snoi2017]一个简单的询问

    Description

    给你一个长度为N的序列ai,1≤i≤N和q组询问,每组询问读入l1,r1,l2,r2,需输出 
    get(l,r,x)表示计算区间[l,r]中,数字x出现了多少次。

    Input

    第一行,一个数字N,表示序列长度。
    第二行,N个数字,表示a1~aN
    第三行,一个数字Q,表示询问个数。
    第4~Q+3行,每行四个数字l1,r1,l2,r2,表示询问。
    N,Q≤50000
    N1≤ai≤N
    1≤l1≤r1≤N
    1≤l2≤r2≤N
    注意:答案有可能超过int的最大值

    Output

    对于每组询问,输出一行一个数字,表示答案 

    Sample Input

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

    Sample Output

    4
    1

    正解:莫队算法。

    把每个询问看成一个矩形,拆成$4$个二维前缀和类型的子矩形。

    然后直接用莫队就可以得出答案了,注意这个莫队的姿势和普通莫队有点不一样。。

     1 #include <bits/stdc++.h>
     2 #define il inline
     3 #define RG register
     4 #define ll long long
     5 #define N (200010)
     6 
     7 using namespace std;
     8 
     9 struct data{ int i,l,r,v; }q[N];
    10 
    11 int a[N],bl[N],cntl[N],cntr[N],Q,n,cnt,block;
    12 ll ans[N];
    13 
    14 il int gi(){
    15   RG int x=0,q=1; RG char ch=getchar();
    16   while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    17   if (ch=='-') q=-1,ch=getchar();
    18   while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
    19   return q*x;
    20 }
    21 
    22 il int cmp(const data &a,const data &b){
    23   if (bl[a.l]==bl[b.l]) return a.r<b.r; return bl[a.l]<bl[b.l];
    24 }
    25 
    26 int main(){
    27 #ifndef ONLINE_JUDGE
    28   freopen("query.in","r",stdin);
    29   freopen("query.out","w",stdout);
    30 #endif
    31   n=gi(),block=sqrt(n);
    32   for (RG int i=1;i<=n;++i) a[i]=gi(),bl[i]=(i-1)/block+1; Q=gi();
    33   for (RG int i=1,l1,r1,l2,r2;i<=Q;++i){
    34     l1=gi(),r1=gi(),l2=gi(),r2=gi();
    35     q[++cnt]=(data){i,r1,r2,1};
    36     q[++cnt]=(data){i,l1-1,r2,-1};
    37     q[++cnt]=(data){i,r1,l2-1,-1};
    38     q[++cnt]=(data){i,l1-1,l2-1,1};
    39   }
    40   for (RG int i=1;i<=cnt;++i) if (q[i].l>q[i].r) swap(q[i].l,q[i].r);
    41   sort(q+1,q+cnt+1,cmp); RG int L=0,R=0; RG ll Ans=0;
    42   for (RG int i=1;i<=cnt;++i){
    43     if (!q[i].l || !q[i].r) continue;
    44     while (L>q[i].l) Ans-=cntr[a[L]],--cntl[a[L--]];
    45     while (R<q[i].r) ++cntr[a[++R]],Ans+=cntl[a[R]];
    46     while (L<q[i].l) ++cntl[a[++L]],Ans+=cntr[a[L]];
    47     while (R>q[i].r) Ans-=cntl[a[R]],--cntr[a[R--]];
    48     ans[q[i].i]+=1LL*q[i].v*Ans;
    49   }
    50   for (RG int i=1;i<=Q;++i) printf("%lld
    ",ans[i]); return 0;
    51 }
  • 相关阅读:
    linux上实现jmeter分布式压力测试(转)
    The more,the better。
    DP_括号匹配序列问题
    MySQL基础语句
    大端模式和小端模式
    C++:bitset用法
    TCP三次握手和四次握手
    静态库与动态库
    DP_最长公共子序列/动规入门
    二维数组和指针
  • 原文地址:https://www.cnblogs.com/wfj2048/p/7499315.html
Copyright © 2011-2022 走看看