HDU 4358 Boring counting(树状数组离线操作+欧拉序列)
来源:互联网 发布:江苏运时数据 编辑:程序博客网 时间:2024/06/05 15:11
题目大意:
有一颗树,树上的每个端点都有序号,并且每个端点都有个权重。
问以某个端点为根节点的子树中,出现了k次的权重的个数。
解决方法:
先dfs一下,将树转化为区间。
先将区间排序(按照左端点的大小),建立一个vector <int> po[i] 数组,记录到目前为止,i出现的位置(按照顺序)。
然后从右向左对数字进行处理,并记录数字出现的位置,对于每个数进行如下操作:
<span style="font-family:KaiTi_GB2312;"><strong>if (po[vis[pos]].size()>=k){ add(po[vis[pos]][po[vis[pos]].size()-k],-2); } if (po[vis[pos]].size()>k){ add(po[vis[pos]][po[vis[pos]].size()-k-1],1); } po[vis[pos]].push_back(pos); if (po[vis[pos]].size()>=k){ add(po[vis[pos]][po[vis[pos]].size()-k],1); }</strong></span>求某段区间的答案就是sum(右区间)。
我的代码:
#include <cstdio>#include <vector>#include <algorithm>#include <iostream>#include <cstring>#define maxn 1001000using namespace std;int n,k,m;struct Node { int x,y;}lsh[maxn],query[maxn];struct quetion{ int x,y,id,ans;}query1[maxn];int num[maxn];int vis[maxn],totl;vector <int> nod[maxn];bool cmp1(Node a,Node b){ return a.x<b.x||a.x==b.x&&a.y<b.y;}int cmp2(quetion a,quetion b){ return a.y<b.y||a.y==b.y&&a.x<b.x||a.x==b.x&&a.y==b.y&&a.id<b.id;}int cmp3(quetion a,quetion b){ return a.id<b.id;}int lshb() {//数据离散化 int totl=2; sort(lsh+1,lsh+n+1,cmp1); num[lsh[1].y]=1; for (int i=2;i<=n;i++){ if (lsh[i].x==lsh[i-1].x){ num[lsh[i].y]=totl-1; } else { num[lsh[i].y]=totl++; } } return 0;}int dfs(int v) { //求欧拉序列 query[v].x=totl++; vis[totl-1]=num[v]; for (int i=0;i<nod[v].size();i++) dfs(nod[v][i]); query[v].y=totl-1; return 0;}int tree[maxn];int add(int x,int v){ for (int i=x;i<=n;i+=i&(-i)) tree[i]+=v; return 0;}int sum(int x){ int ans=0; for (int i=x;i>0;i-=i&(-i)) ans+=tree[i]; return ans;}vector <int> po[maxn];int change(int pos){ if (po[vis[pos]].size()>=k){ add(po[vis[pos]][po[vis[pos]].size()-k],-2); } if (po[vis[pos]].size()>k){ add(po[vis[pos]][po[vis[pos]].size()-k-1],1); } po[vis[pos]].push_back(pos); if (po[vis[pos]].size()>=k){ add(po[vis[pos]][po[vis[pos]].size()-k],1); } return 0;}int main (){ //freopen("test.in","r",stdin); int T,t=1;scanf("%d",&T); while (T--){ memset(tree,0,sizeof(tree)); printf("Case #%d:\n",t++); scanf("%d%d",&n,&k); for (int i=1;i<=n;i++) scanf("%d",&lsh[i].x),lsh[i].y=i,nod[i].clear(),po[i].clear(); lshb(); //for (int i=1;i<=n;i++) printf("%d ",num[i]);printf("\n"); for (int i=1;i<=n-1;i++){ int a,b;scanf("%d%d",&a,&b); nod[a].push_back(b); } totl=1;dfs(1);scanf("%d",&m); for (int i=1;i<=m;i++){ int a;scanf("%d",&a); query1[i].x=query[a].x; query1[i].y=query[a].y; query1[i].id=i; query1[i].ans=0; } sort(query1+1,query1+1+m,cmp2);int pos=1; for (int i=1;i<=m;i++){ while (pos<=query1[i].y){ change(pos); pos++; } if (query1[i].x>1) query1[i].ans=sum(query1[i].y)-sum(query1[i].x-1); else query1[i].ans=sum(query1[i].y); } sort(query1+1,query1+1+m,cmp3); for (int i=1;i<=m;i++) printf("%d\n",query1[i].ans); if (T!=0) printf("\n"); } return 0;}
0 0
- HDU 4358 Boring counting(树状数组离线操作+欧拉序列)
- HDU 4358 Boring counting(离线 + 树状数组)
- HDU 4358 Boring counting(树状数组)
- HDU 4358 Boring counting (树状数组)
- HDU Boring counting 树状数组
- HDU 4358 Boring counting(树的遍历+树状数组+离散化+离线处理)
- HDU 4358-I - Boring counting-dfs序+离线+树状数组/线段树
- hdu 4358 Boring counting 线段树离线操作
- sdut2610---Boring Counting(离线+树状数组+离散化)
- hdu 3518 Boring counting(后缀数组)
- HDU 3518Boring counting(后缀数组)
- HDU 4358 - Boring counting
- hdu 4358 Boring counting
- hdu 4358 Boring counting
- HDU 4358 Boring counting
- HDU 4358 Boring counting(线段树)
- HDU 3874 Necklace(树状数组 && 离线操作)
- HDU 3874 Necklace (树状数组+离线操作)
- Android和iOS中Cocos2dx的横屏竖屏设置
- 修改tomcat默认iso8859-1的编码编码方式 .
- ORA-01720: grant option does not exist for 'xxx.xxxx'
- DBM
- 让c/c++代码更好的缩进
- HDU 4358 Boring counting(树状数组离线操作+欧拉序列)
- 详解php解析xml用法
- python time模块详解
- Linux关闭防火墙命令
- CSS中的绝对定位与相对定位
- oracle authid current_user详解
- 获取当前日期的星期&获取前几天,后几天的日期的工具类
- G - Vases and Flowers(线段树+二分)
- 详解oracle用户创建(create user)