zoukankan      html  css  js  c++  java
  • 2019.8.3 [HZOI]NOIP模拟测试12 B. 数颜色

    2019.8.3 [HZOI]NOIP模拟测试12 B. 数颜色

    全场比赛题解:https://pan.baidu.com/s/1eSAMuXk
    数据结构学傻的做法:
    对每种颜色开动态开点线段树直接维护
    操作一区间查询 操作二转化为单点修改
    常数有点大,需要稍微卡常。

    正解:
    对每种颜色开vector存储出现位置(下标),可以发现每种颜色出现位置满足单调性,操作一直接二分找到这段区间,操作二找到两个位置修改。

    Code:

    #include <bits/stdc++.h>
    using namespace std;
    const int N=6e7+5;
    int n,m,tot,ans,a[N],rt[N],ls[N],rs[N],sum[N];
    #define mid ((l+r)>>1)
    void In(int &num){
    	register char c=getchar();
    	for(num=0;!isdigit(c);c=getchar());
    	for(;isdigit(c);num=num*10+c-48,c=getchar()); 
    }
    void add(int &p,int l,int r,int pos,int val){
    	if(!p) p=++tot; sum[p]+=val;
    	if(l!=r) pos<=mid?add(ls[p],l,mid,pos,val):add(rs[p],mid+1,r,pos,val);
    }
    void query(int p,int l,int r,int L,int R){
    	if(!p) return;
    	if(L<=l&&r<=R) return (void) (ans+=sum[p]);
    	if(L<=mid&&ls[p]&&sum[ls[p]]>0) query(ls[p],l,mid,L,R);
    	if(R>mid&&rs[p]&&sum[rs[p]]>0) query(rs[p],mid+1,r,L,R);
    }
    int main(){
    	In(n);In(m);
    	for(register int i=1;i<=n;++i){
    		In(a[i]);++a[i];
    		add(rt[a[i]],1,n,i,1);
    	}
    	for(register int i=1,op,l,r,c,pos;i<=m;++i){
    		In(op);
    		if(op==1) {
    			ans=0;
    			In(l);In(r);In(c);++c;
    			query(rt[c],1,n,l,r);
    			printf("%d
    ",ans);
    		}
    		else {
    			In(pos);
    			add(rt[a[pos]],1,n,pos,-1);
    			add(rt[a[pos]],1,n,pos+1,1);
    			add(rt[a[pos+1]],1,n,pos+1,-1);
    			add(rt[a[pos+1]],1,n,pos,1);
    			swap(a[pos],a[pos+1]);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    魔术球问题
    【模板】网络最大流
    [SCOI2010]股票交易
    [SCOI2009]生日礼物
    [HAOI2007]修筑绿化带
    [HAOI2007]理想的正方形
    [USACO12MAR]花盆Flowerpot
    滑动窗口
    斐波那契公约数
    [SDOI2008]仪仗队
  • 原文地址:https://www.cnblogs.com/yu-xing/p/11295512.html
Copyright © 2011-2022 走看看