zoukankan      html  css  js  c++  java
  • [CSP-S模拟测试]:计划(前缀和)

    题目传送门(内部题32)


    输入格式

    第一行,三个正整数$n,m,q$。
    第二行,$n$个正整数$a_i$,保证$1leqslant a_ileqslant n$。
    接下来$q$行,每行两个正整数$k,l$,保证$k<l$。


    输出格式

    输出$q$行,表示每个旅行计划询问的答案。


    样例

    样例输入:

    7 2 7
    6 1 3 6 4 6 5
    1 2
    4 6
    2 7
    6 7
    1 2
    1 4
    2 6

    样例输出:

    1
    4
    35
    1
    1
    10
    20


    数据范围与提示

    对于$20\%$的数据,$2leqslant n,qleqslant 100$。
    对于$40\%$的数据,$2leqslant n,qleqslant 1,000$。
    对于$80\%$的数据,$2leqslant n,qleqslant 10,000$。
    对于$100\%$的数据,$2leqslant n,qleqslant 100,000,1leqslant mleqslant n,1leqslant a_ileqslant n,1leqslant k < lleqslant n$。


    题解

    我们可以$Theta(n^2)$的时间内求出对于每个左端点,最靠左的不乏味点的位置。

    维护四个前缀和。

    对于每一次询问,二分求出右端点,然后$Theta(1)$前缀和就好了。

    时间复杂度:$Theta(n^2+qlog n)$。

    期望得分:$100$分。

    实际得分:$100$分。


    代码时刻

    #include<bits/stdc++.h>
    using namespace std;
    int n,m,q;
    int a[100001],sum,vis[100001];
    long long cnt[100001];
    pair<pair<long long,long long>,pair<long long,long long> > pos[100001];
    int main()
    {
    	scanf("%d%d%d",&n,&m,&q);
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%d",&a[i]);
    		cnt[i]=n+1;
    	}
    	vis[0]=sum=1;
    	for(int i=1;i<=n;i++)
    	{
    		vis[a[i-1]]--;
    		if(vis[a[i-1]]){cnt[i]=cnt[i-1];continue;}
    		sum--;
    		for(int j=cnt[i-1]+1;j<=n;j++)
    		{
    			if(!vis[a[j]])sum++;
    			vis[a[j]]++;
    			if(sum>=m)
    			{
    				cnt[i]=j;
    				break;
    			}
    		}
    	}
    	for(int i=1;i<=n;i++)
    	{
    		pos[i].first.first=pos[i-1].first.first+i;
    		pos[i].second.first=pos[i-1].second.first+i*cnt[i];
    		pos[i].first.second=pos[i-1].first.second+cnt[i];
    		pos[i].second.second=pos[i-1].second.second+cnt[i]*cnt[i];
    	}
    	while(q--)
    	{
    		long long l,r;
    		scanf("%lld%lld",&l,&r);
    		long long mid=upper_bound(cnt+l,cnt+r+1,r)-cnt-1;
    		printf("%lld
    ",((r*r+r)*(mid-l+1)-((r+1)*(pos[mid].first.first-pos[l-1].first.first)<<1)+pos[mid].first.second-pos[l-1].first.second+((pos[mid].second.first-pos[l-1].second.first)<<1)-pos[mid].second.second+pos[l-1].second.second)>>1);
    	}
    	return 0;
    }
    

    rp++

  • 相关阅读:
    excel的导入导出
    mybatis常用sql
    java中和时间相关的类,方法
    <resultMap>
    项目启动报的错
    多表查询
    file的一些方法
    AOV网络与AOE网络
    封装解封装过程
    以太网交换机
  • 原文地址:https://www.cnblogs.com/wzc521/p/11480022.html
Copyright © 2011-2022 走看看