• HDU 4358


    看了题解那个弱化版后,马上就去做了HDU 3333这道题,发现有可用的地方。于是往这方面想,主要是处理如何确定一个数出现K次的问题。想到了从左往右把每个数出现的次数记下来,但感觉不是这样,呃,再看别人做的,真的是这样的--!

    主要是处理一个数出现K次后的情况,把每个数出现的位置记录下来,当出现大于等于K次时,假设此时已出现sz个,则把sz-k这个位置加1,把之前的SZ-K-1的位置-2,使之状态是-1(因为之前刚好出现K次时就已加1)。于是当查询到右端点时,求出区间和,+1和-1刚好消去。需要注意的是,当SZ-K-2>=0时,应当把SZ-K-2之前为-1的位置置成0,即加1。这样结果才是正确的。

    至于把树映射到数组,很简单,使用DFS+时间戳的方法就可以了,记录每个结点第一次出现的次序以及深搜完以该结点为根的子树的最后一个时间戳即可。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <map>
    #include <vector>
    #define LL __int64
    #define lowbit(x) ((x)&(-x))
    using namespace std;
    
    const int N=100100;
    const int Q=100100;
    
    struct Query{
    	int l,r,Id;
    	Query(){}
    	Query(int ll,int rr,int d){
    		l=ll; r=rr; Id=d;
    	}
    	bool operator <(const Query &a)const{
    		if(r<a.r) return true;
    		return false;
    	}
    };
    Query query[Q];
    LL su[N],ans[Q];
    int num[N],val[N];
    struct Node{
    	int bgn,en;
    };
    Node node[N];
    vector<int>pos[N];
    int n,k,q,tot,DEP;
    
    struct Edge{
    	int u,v,next;
    }edge[N*2];
    int head[N];
    
    void addedge(int u,int v){
    	edge[tot].u=u;
    	edge[tot].v=v;
    	edge[tot].next=head[u];
    	head[u]=tot++;
    }
    
    LL sum(int x){
          if(x==0) return 0;
          LL s=0;
          for(;x;x-=lowbit(x)){
          s+=su[x];
          }
          return s;
    }
    
    void update(int x,LL w){
         for(;x<=n;x+=lowbit(x))
         su[x]+=w;
    }
    
    void dfs(int u,int f){
    	++DEP;
    	node[u].bgn=DEP;
    	val[DEP]=num[u];
    	for(int e=head[u];e!=-1;e=edge[e].next){
    		int v=edge[e].v;
    		if(v!=f){
    			dfs(v,u);
    		}
    	}
    	node[u].en=DEP;
    }
    
    int main(){
    	int T,t=0,u,v,cnt=0;
    	scanf("%d",&T);
    	while(++t<=T){
    		map<int,int>mp;
    		tot=0;DEP=0;
    		cnt=0;
    		scanf("%d%d",&n,&k);
    		for(int i=1;i<=n;i++){
    			scanf("%d",&num[i]);
    			head[i]=-1;
    			su[i]=0;
    			pos[i].clear();
    			if(!mp[num[i]])
    			mp[num[i]]=++cnt;
    		}
    		for(int i=1;i<n;i++){
    			scanf("%d%d",&u,&v);
    			addedge(u,v);
    			addedge(v,u);
    		}
    		dfs(1,0);
    		scanf("%d",&q);
    		for(int i=1;i<=q;i++){
    			scanf("%d",&cnt);
    			query[i]=Query(node[cnt].bgn,node[cnt].en,i);
    		}
    		sort(query+1,query+1+q);
    		cnt=1;
    		int sz;
    		for(int i=1;i<=n;i++){
    			int t=mp[val[i]];
    			pos[t].push_back(i);
    			sz=pos[t].size();
    			if(sz>=k){
    				if(sz==k){
    					update(pos[t][sz-k],1);
    				}
    				else{
    					update(pos[t][sz-k-1],-2);
    					update(pos[t][sz-k],1);
    				}
    				if(sz-k-2>=0)
    				update(pos[t][sz-k-2],1);
    			}
    			while(query[cnt].r==i){
    				ans[query[cnt].Id]=sum(query[cnt].r)-sum(query[cnt].l-1);
    				cnt++;
    			}
    		}
    		printf("Case #%d:
    ",t);
    		for(int i=1;i<=q;i++)
    		printf("%I64d
    ",ans[i]);
    		if(t<T)
    		puts("");
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    跳台阶问题
    腾讯,百度,网易游戏,华为笔面经验
    进程、线程、应用程序之间的关系
    const用法小结
    vc快捷键
    文献阅读以及如何管理
    数据类型转换
    vc Debug Release
    如何阅读文献
    如何提高表达能力
  • 原文地址:https://www.cnblogs.com/jie-dcai/p/4272438.html
Copyright © 2020-2023  润新知