zoukankan      html  css  js  c++  java
  • 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;
    }
    

      

  • 相关阅读:
    Js中的正则表达式
    js内存泄露的几种情况
    JavaScript的setTimeout与setInterval执行时机
    IE模拟addDOMLoadEvent和jQuery的ready实现
    谈谈JavaScript的异步实现
    在iOS7中修改状态栏字体的颜色
    IOS 疯狂基础之 页面间跳转
    ATL2.1版的CString分析
    翻译: 如何改变MFC应用程序主窗口的类名
    VC5.0中的ATL的一个有趣的bug
  • 原文地址:https://www.cnblogs.com/jie-dcai/p/4272438.html
Copyright © 2011-2022 走看看