zoukankan      html  css  js  c++  java
  • 洛谷 P1494 [国家集训队]小Z的袜子(莫队)

    题目链接:https://www.luogu.com.cn/problem/P1494

    一道很经典的莫队模板题,然而每道莫队题的大体轮廓都差不多。

    首先莫队是一种基于分块的算法,它的显著特点就是:

    能在$O(1)$的时间内从$(l,r)$转换到$(l,r-1),(l-1,r),(l+1,r),(l,r+1)$。

    然后它的总复杂度在$O(n imes sqrt{n})$左右。

    这道题中除了莫队的应用外,还需要处理一个组合数$(cul)$和一个$gcd$,然后跑莫队即可。

    AC代码:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<algorithm>
     5 
     6 using namespace std;
     7 typedef long long ll;
     8 const int N=1000000+10;
     9 
    10 int a[N],vis[N];
    11 int ans1[N],ans2[N];
    12 ll ans;
    13 int block;
    14 
    15 struct node{
    16     int l,r;
    17     int id;
    18 }q[N];
    19 
    20 ll cul(ll x){
    21     return x*(x-1)/2;
    22 }
    23 
    24 bool cmp(node aa,node bb){
    25     if(aa.l/block==bb.l/block) return aa.r<bb.r;
    26     return aa.l/block<bb.l/block; 
    27 }
    28 
    29 void add(int pos){
    30     vis[a[pos]]++;
    31     ll m=vis[a[pos]];
    32     ans=ans-cul(m-1)+cul(m);
    33 }
    34 
    35 void del(int pos){
    36     vis[a[pos]]--;
    37     ll m=vis[a[pos]];
    38     ans=ans-cul(m+1)+cul(m);
    39 }
    40 
    41 int gcd(int n,int m){
    42     if(m==0) return n;
    43     return gcd(m,n%m);
    44 }
    45 
    46 int main(){
    47     int n,m;
    48     scanf("%d%d",&n,&m);
    49     block=sqrt(n);
    50     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    51     int L=1,R=0;
    52     for(int i=1;i<=m;i++){
    53         scanf("%d%d",&q[i].l,&q[i].r);
    54         q[i].id=i;    
    55     }
    56     sort(q+1,q+m+1,cmp);
    57     for(int i=1;i<=m;i++){
    58         while(L<q[i].l){
    59             del(L);
    60             L++;
    61         }
    62         while(L>q[i].l){
    63             L--;
    64             add(L);
    65         }
    66         while(R>q[i].r){
    67             del(R);
    68             R--;
    69         }
    70         while(R<q[i].r){
    71             R++;
    72             add(R);
    73         }
    74         ans1[q[i].id]=ans;
    75         ans2[q[i].id]=cul(q[i].r-q[i].l+1);
    76     }
    77     for(int i=1;i<=m;i++){
    78         int g=gcd(ans1[i],ans2[i]);
    79         if(ans1[i]==0){
    80             printf("0/1
    ");
    81             continue;
    82         }
    83         printf("%d/%d
    ",ans1[i]/g,ans2[i]/g);
    84     }
    85     return 0;
    86 }
    AC代码
  • 相关阅读:
    ftp上传下载
    阿里云轻量服务器价格及轻量与ECS服务器区别比较
    找工作
    程序员的精力管理
    应届生如何笔试面试
    java重点总结(一)
    真是面试题汇总(二)
    真实笔试题汇总(一)
    真实面试问题汇总(一)
    Java后端面试准备
  • 原文地址:https://www.cnblogs.com/New-ljx/p/12271257.html
Copyright © 2011-2022 走看看