zoukankan      html  css  js  c++  java
  • 旅行计划

    题目描述

    给定一串数 a下标从1到n,并给出 q 组询问,每次询问[k,l]中满足 k<=i<j<=l 且[i,j]中出现不同的数超过m种的(j-i)之和

    Solution

    首先求出对于每个j,能使他中间出现m个数的位置,记作e[j],那么对于每个e[j]>=k,区间[e[j]-1,j]...[k,j]都是合法的

    因为 ej>=k 的条件已经包含了j>=k,所以只需查询 j≤l 且 e j ≥k 的所有 e[j] 的和、j的和、S(e[j])的和、j的个数。这里有两个限制,可以通过排序解决一个限制,另一个用树状数组维护。可以将询问离线后按右端点 l 排序,然后从小到大枚举右端点 j,先将当前 j的四个值加入到树状数组的 e
    j 位置处(此时树状数组中存的是所有j'<=j 的值),再处理所有 l=j 的询问,即查询此时树状数组中所有 ≥k 处的和。

    
    /*Code by Codercjh*/
    #include<bits/stdc++.h>
    #define fr(i,a,b) for(int i=(a);i<=(b);++i)
    #define rf(i,a,b) for(int i=(a);i>=(b);--i)
    #define min(a,b) (a<b?a:b)
    #define max(a,b) (a>b?a:b)
    using namespace std;
    typedef long long ll;
    template<typename T>
    inline void read(T &x){
    	char c=getchar();T fh=0;bool f=false;
    	while(!isdigit(c))f|=(c=='-'),c=getchar();
    	while(isdigit(c))fh=(fh<<1)+(fh<<3)+(c^48),c=getchar();
    	x=f?-fh:fh;
    	return;
    }
    const int N=1e5+5;
    int a[N],n,m,t,cnt[N],e[N];
    struct node{int l,r,id;ll ans;}q[N];
    bool cmp(node a,node b){return a.r<b.r;}
    bool cmp1(node a,node b){return a.id<b.id;}
    ll tr[N][5],s[N];
    #define lowbit(x) (x&-x)
    inline void add(int x,ll v,int tp){for(;x<=n;x+=lowbit(x))tr[x][tp]+=v;}
    inline ll ask(int x,int tp){ll ans=0;for(;x;x-=lowbit(x))ans+=tr[x][tp];return ans;}
    void Add(int x){
    	if(!e[x])return;
    	add(e[x],1ll*x*e[x],1);
    	add(e[x],x,2);
    	add(e[x],s[e[x]],3);
    	add(e[x],1,4);
    }
    ll Ask(int l,int r){
    	ll t1=ask(r,1)-ask(l-1,1),
    		t2=ask(r,2)-ask(l-1,2),
    		t3=ask(r,3)-ask(l-1,3),
    		t4=ask(r,4)-ask(l-1,4);
    	return t1-t2*(l-1)-t3+s[l-1]*t4;
    }
    int main(){
    	read(n),read(m),read(t);
    	fr(i,1,n)read(a[i]),s[i]=s[i-1]+i;
    	fr(i,1,t)read(q[i].l),read(q[i].r),q[i].id=i;
    	sort(q+1,q+t+1,cmp);
    	int i=1,j=1,tot=1;cnt[a[1]]=1;
    	while(j<=n){
    		while(tot>=m&&i<=n){
    			if(tot==m&&cnt[a[i]]==1)break;
    			if(--cnt[a[i]]==0)--tot;
    			++i;
    		}
    		if(tot>=m)e[j]=i;
    		if(++cnt[a[++j]]==1)++tot;
    	}
    	j=0;
    	fr(i,1,t){
    		while(++j<=q[i].r)Add(j);if(j>q[i].r)--j;
    		q[i].ans=Ask(q[i].l,q[i].r);
    	}
    	sort(q+1,q+t+1,cmp1);
    	fr(i,1,n)printf("%lld
    ",q[i].ans);
    	return 0;
    }
    
  • 相关阅读:
    scss-变量分隔符
    scss-声明变量与引用
    scss-入门
    关于动画框架类注意的点点滴滴03
    关于动画框架类注意的点点滴滴02
    关于动画框架类注意的点点滴滴01
    简单的form表单
    简易自定义下拉菜单 与简易默认下拉html片段
    有边框的简易表格
    css模仿表格 居中
  • 原文地址:https://www.cnblogs.com/coder-cjh/p/13525690.html
Copyright © 2011-2022 走看看