zoukankan      html  css  js  c++  java
  • 小B的询问

    题目描述

    小B有一个序列,包含N个1~K之间的整数。他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重复次数。小B请你帮助他回答询问。

    对于全部的数据,1<=N、M、K<=50000

    题解

    分块可以做,考虑怎么当端点移动时,怎么维护答案。

    当区间扩张到i,只对c(i)有影响,所以只有c(i)的值变成(c(i)+1),那么答案就很好维护了,增加了2*c(i)+1

    当区间缩短,同理只有c(i)变成(c(i)-1),所以减去(2*c(i)-1)

    只要是记录一下莫队模板

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn=50005;
    int n,m,k,ret;
    int a[maxn],cnt[maxn];
    int size,pos[maxn];
    int ans[maxn];
    struct question{
        int l,r,id;
    }q[maxn];
    template<class T>inline void read(T &x){
        x=0;char ch=getchar();
        while(!isdigit(ch)) ch=getchar();
        while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    }
    
    bool cmp(question a,question b){
        if(pos[a.l]==pos[b.l]) return a.r<b.r;
        return pos[a.l]<pos[b.l];
    }
    
    void add(int x){
        ret+=2*cnt[a[x]]+1;
        cnt[a[x]]++;
    }
    
    void del(int x){
        ret-=2*cnt[a[x]]-1;
        cnt[a[x]]--;
    }
    
    int main(){
        read(n);read(m);read(k);
        size=sqrt(n+0.5);
        for(int i=1;i<=n;i++){read(a[i]);pos[i]=(i-1)/size+1;}
        for(int i=1;i<=m;i++){read(q[i].l);read(q[i].r);q[i].id=i;}
        sort(q+1,q+m+1,cmp);
        int nowl=1,nowr=0;
        for(int i=1;i<=m;i++){
            while(nowl>q[i].l) add(--nowl);
            while(nowr<q[i].r) add(++nowr);
            while(nowl<q[i].l) del(nowl++);
            while(nowr>q[i].r) del(nowr--);
            ans[q[i].id]=ret;
        }
        for(int i=1;i<=m;i++) printf("%d
    ",ans[i]);
    }
    View Code
  • 相关阅读:
    网络流24题 餐巾计划(DCOJ8008)
    网络流24题 负载平衡(DCOJ8013)
    tyvj1982 武器分配
    bzoj1877 晨跑
    bzoj1834 网络扩容
    草地排水 改了又改(DCOJ6013)
    codevs1033 蚯蚓的游戏问题
    codevs1227 方格取数2
    bzoj1412 狼和羊的故事
    codevs1839 洞穴勘测
  • 原文地址:https://www.cnblogs.com/sto324/p/11234656.html
Copyright © 2011-2022 走看看