zoukankan      html  css  js  c++  java
  • ●BZOJ 2743 [HEOI2012]采花

    题链:

    http://www.lydsy.com/JudgeOnline/problem.php?id=2743

    题解:

    树状数组,离线

    求区间里面有多少种出现次数大于等于 2 的颜色。
    类似某一个题,问的是区间里面有多少种不同的颜色(即出现次数大于等于 1 )。
     
    把询问离线,并按右端点 r 从小到大排序。
    并维护出 last[i] 表示与 i 位置颜色相同的上一个位置。
    然后从左到右枚举右端点 i,
    在树状数组中把 last[last[i]] 位置(如果不为 0 的话)的值 -1,
    把 last[i] 位置(如果不为 0 的话)的值 +1
    (也就是只给距离当前枚举到的 i位置第二近的并且和i位置颜色相同的那个位置打上标记)
    然后回答右端点在 i 处的询问即可。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 1000500
    using namespace std;
    int last[MAXN],pos[MAXN],ANS[MAXN];
    int N,C,M;
    struct Question{
    	int l,r,id;
    	bool operator <(const Question &rtm)const{
    		return r<rtm.r;
    	}
    }Q[MAXN];
    struct BIT{
    	int A[MAXN],N;
    	void Reset(int n){N=n;}
    	int Lowbit(int x){return x&-x;}
    	void Modify(int p,int x){
    		while(p<=N) A[p]+=x,p+=Lowbit(p);
    	}
    	int Query(int p){
    		static int ret; ret=0;
    		while(p) ret+=A[p],p-=Lowbit(p);
    		return ret;
    	}
    }DT;
    char gc(){
    	static char s[300010];
    	static int bit=300000,len,p;
    	if(p>=len) len=fread(s,1,bit,stdin),s[len]=EOF,p=0;
    	return s[p++];
    }
    void read(int &x){
    	static int f; static char ch;
    	x=0; f=1; ch=gc();
    	while(ch<'0'||'9'<ch){if(ch=='-')f=-1;ch=gc();}
    	while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=gc();}
    	x=x*f;
    }
    void write(int x){
    	static char s[20]; static int p;
    	if(!x) putchar('0');
    	if(x<0) putchar('-'),x=-x;
    	while(x) s[p++]=x%10+'0',x/=10;
    	while(p) putchar(s[--p]); 
    	putchar('
    ');
    }
    int main(){
    	read(N); read(C); read(M);
    	for(int i=1,a;i<=N;i++)
    		read(a),last[i]=pos[a],pos[a]=i;
    	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);
    	DT.Reset(N);
    	for(int i=1,j=1;i<=N;i++){
    		if(last[last[i]]) DT.Modify(last[last[i]],-1);
    		if(last[i]) DT.Modify(last[i],1);
    		while(Q[j].r==i&&j<=M){
    			ANS[Q[j].id]=DT.Query(Q[j].r)-DT.Query(Q[j].l-1);
    			j++;
    		}
    	}
    	for(int i=1;i<=M;i++) write(ANS[i]);
    	return 0;
    }
    

  • 相关阅读:
    Python Revisited Day 13 (正则表达式)
    Python Revisited Day 06 (面向对象程序设计)
    Python Revisited (变量)
    Python Revisited Day 05(模块)
    Python Revisited Day 04 (控制结构与函数)
    Python Revisited Day 03 (组合数据类型)
    Numpy
    Python Revisited Day 01
    Python3使用openpyxl读写Excel文件
    Python3操作YAML文件
  • 原文地址:https://www.cnblogs.com/zj75211/p/8075988.html
Copyright © 2011-2022 走看看