区间查询问题
2015-05-31 07:55
357 查看
问题:In your childhood, do you crazy for collecting the beautiful cards in the snacks? They said that, for example, if you collect all the 108 people in the famous novel Water Margin, you will win an amazing award.
As a smart boy, you notice that to win the award, you must buy much more snacks than it seems to be. To convince your friends not to waste money any more, you should find the expected number of snacks one should buy to collect a full suit of cards.
Input
The first line of each test case contains one integer N (1 <= N <= 20), indicating the number of different cards you need the collect. The second line contains N numbers p1, p2, ..., pN, (p1 + p2 + ... + pN <= 1), indicating the possibility of each card to appear in a bag of snacks.
Note there is at most one card in a bag of snacks. And it is possible that there is nothing in the bag.
Output
Output one number for each test case, indicating the expected number of bags to buy to collect all the N different cards.
You will get accepted if the difference between your answer and the standard answer is no more that 10^-4.
Sample Input
1
0.1
2
0.1 0.4
Sample Output
10.000
10.500
回答:题意:
给你 n个点。他们有 上下级关系,一个点只有一个上级,一个上级 可以有多个下级,每个点有两个属性,能力值 、忠诚度(每个节点的忠诚度不同),求我们要删除 一个节点, 则我们 需从 其下级中选出 一个节点,其能力值 比该节点 要高,且忠诚度是(比其能力高的下级节点中的)最高
题解:
首先将树状结构,转化为线状结构,
可以遍历一遍将树上每个点标记为一维区间上的某个点,且在同一棵子树内的点是连续的一段。
然后,将所有点按能力从大到小排序,能力相同的编号小的排在前面,然后扫描一遍,扫描时维护一颗线段树,
(我们先插入线段树的是,比其能力值 大的,我们只要从这些里面找到,忠诚度最高的就可以了)
先查找该点为根节点的子树内的最优值,然后插入该点的忠诚度。
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#define maxn 100110
#define mod 100000007
#define eps 1e-6;
#define ll long long
#define M 15520
using namespace std;
map<int,int>map1;
vector<int>g[maxn] ;
int num ,ans[maxn],n,m,l[maxn],r[maxn];
struct staff
{
int loy;
int abt;
int id;
}sta[maxn];
struct node
{
int l;
int r;
int mx;
}p[maxn * 2];
bool cmp (staff a, staff b)
{
return a.abt > b.abt ;
}
void dfs(int x)//编号变为线状结构
{
l[x] = num++;
for(int i = 0; i < g[x].size(); ++i)
{
dfs(g[x][i]);
}
r[x] = num ;
}
void build(int x,int l,int r)
{
p[x].l = l;
p[x].r = r;
p[x].mx = -1 ;
if(l == r) return ;
int mid = (l + r) /2;
build(x*2,l,mid);
build(x*2+1,mid + 1,r);
}
int get(int x,int l,int r)
{
if( r < l ) return -1 ;
if(p[x].l == l && p[x].r == r)
{
return p[x].mx;
}
int mid = (p[x].l + p[x].r) /2 ;
if(r <= mid) return get(x * 2,l,r);
else
{
if(l > mid) return get(x * 2 + 1,l,r);
else
{
return max(get(x * 2,l,mid),get(x * 2 + 1,mid + 1,r));
}
}
}
void insert(int x,int pos,int d)
{
if(p[x].l == p[x].r )
{
p[x].mx = d;
return ;
}
int mid = (p[x].l + p[x].r) /2 ;
if(pos <= mid) insert(x*2,pos,d);
else
{
insert(x*2 + 1, pos,d);
}
p[x].mx = max(p[x*2].mx,p[x*2+1].mx);
}
void init()
{
for( int i = 0; i <= n; ++i )
g[i].clear();
map1.clear();
num = 0 ;
}
int main()
{
int t,u,loy,abt,a,j,i;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
init();
for( i = 1 ; i < n; ++i)
{
scanf("%d%d%d",&u,&loy,&abt);
g[u].push_back(i);
sta[i].loy = loy;
sta[i].abt = abt ;
sta[i].id = i;
map1[loy] = i;
}
dfs(0);
build(1,0,num - 1);
sort(sta + 1,sta + n,cmp);//排序为了下面 查询 打基础,排好序之后,我们插入时,保证了,比 i 大的已经插入了这时直接找,忠诚的uida就可以了
for( i = 1 ; i < n ; i = j)
{
j = i;
while(j < n &&sta[i].abt == sta[j].abt)
{
int id = sta[j].id ;
loy = get(1,l[id] + 1,r[id] - 1);
if(loy != -1) ans[id] = map1[loy] ;
else ans[id] = -1;
++j;
}
j = i ;
while(j < n && sta[i].abt == sta[j].abt )
{
int id = sta[j].id;
insert(1,l[id],sta[j].loy);
++j;
}
}
while(m--)
{
scanf("%d",&a);
printf("%d\n",ans[a]) ;
}
}
return 0;
}
As a smart boy, you notice that to win the award, you must buy much more snacks than it seems to be. To convince your friends not to waste money any more, you should find the expected number of snacks one should buy to collect a full suit of cards.
Input
The first line of each test case contains one integer N (1 <= N <= 20), indicating the number of different cards you need the collect. The second line contains N numbers p1, p2, ..., pN, (p1 + p2 + ... + pN <= 1), indicating the possibility of each card to appear in a bag of snacks.
Note there is at most one card in a bag of snacks. And it is possible that there is nothing in the bag.
Output
Output one number for each test case, indicating the expected number of bags to buy to collect all the N different cards.
You will get accepted if the difference between your answer and the standard answer is no more that 10^-4.
Sample Input
1
0.1
2
0.1 0.4
Sample Output
10.000
10.500
回答:题意:
给你 n个点。他们有 上下级关系,一个点只有一个上级,一个上级 可以有多个下级,每个点有两个属性,能力值 、忠诚度(每个节点的忠诚度不同),求我们要删除 一个节点, 则我们 需从 其下级中选出 一个节点,其能力值 比该节点 要高,且忠诚度是(比其能力高的下级节点中的)最高
题解:
首先将树状结构,转化为线状结构,
可以遍历一遍将树上每个点标记为一维区间上的某个点,且在同一棵子树内的点是连续的一段。
然后,将所有点按能力从大到小排序,能力相同的编号小的排在前面,然后扫描一遍,扫描时维护一颗线段树,
(我们先插入线段树的是,比其能力值 大的,我们只要从这些里面找到,忠诚度最高的就可以了)
先查找该点为根节点的子树内的最优值,然后插入该点的忠诚度。
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#define maxn 100110
#define mod 100000007
#define eps 1e-6;
#define ll long long
#define M 15520
using namespace std;
map<int,int>map1;
vector<int>g[maxn] ;
int num ,ans[maxn],n,m,l[maxn],r[maxn];
struct staff
{
int loy;
int abt;
int id;
}sta[maxn];
struct node
{
int l;
int r;
int mx;
}p[maxn * 2];
bool cmp (staff a, staff b)
{
return a.abt > b.abt ;
}
void dfs(int x)//编号变为线状结构
{
l[x] = num++;
for(int i = 0; i < g[x].size(); ++i)
{
dfs(g[x][i]);
}
r[x] = num ;
}
void build(int x,int l,int r)
{
p[x].l = l;
p[x].r = r;
p[x].mx = -1 ;
if(l == r) return ;
int mid = (l + r) /2;
build(x*2,l,mid);
build(x*2+1,mid + 1,r);
}
int get(int x,int l,int r)
{
if( r < l ) return -1 ;
if(p[x].l == l && p[x].r == r)
{
return p[x].mx;
}
int mid = (p[x].l + p[x].r) /2 ;
if(r <= mid) return get(x * 2,l,r);
else
{
if(l > mid) return get(x * 2 + 1,l,r);
else
{
return max(get(x * 2,l,mid),get(x * 2 + 1,mid + 1,r));
}
}
}
void insert(int x,int pos,int d)
{
if(p[x].l == p[x].r )
{
p[x].mx = d;
return ;
}
int mid = (p[x].l + p[x].r) /2 ;
if(pos <= mid) insert(x*2,pos,d);
else
{
insert(x*2 + 1, pos,d);
}
p[x].mx = max(p[x*2].mx,p[x*2+1].mx);
}
void init()
{
for( int i = 0; i <= n; ++i )
g[i].clear();
map1.clear();
num = 0 ;
}
int main()
{
int t,u,loy,abt,a,j,i;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
init();
for( i = 1 ; i < n; ++i)
{
scanf("%d%d%d",&u,&loy,&abt);
g[u].push_back(i);
sta[i].loy = loy;
sta[i].abt = abt ;
sta[i].id = i;
map1[loy] = i;
}
dfs(0);
build(1,0,num - 1);
sort(sta + 1,sta + n,cmp);//排序为了下面 查询 打基础,排好序之后,我们插入时,保证了,比 i 大的已经插入了这时直接找,忠诚的uida就可以了
for( i = 1 ; i < n ; i = j)
{
j = i;
while(j < n &&sta[i].abt == sta[j].abt)
{
int id = sta[j].id ;
loy = get(1,l[id] + 1,r[id] - 1);
if(loy != -1) ans[id] = map1[loy] ;
else ans[id] = -1;
++j;
}
j = i ;
while(j < n && sta[i].abt == sta[j].abt )
{
int id = sta[j].id;
insert(1,l[id],sta[j].loy);
++j;
}
}
while(m--)
{
scanf("%d",&a);
printf("%d\n",ans[a]) ;
}
}
return 0;
}
相关文章推荐
- ubuntu sudo 和su的区别
- Swift学习笔记-判断字符出现的次数
- 深入探讨 Java 类加载器
- eclipse开发php全过程的搭建带debug的配置
- 长度为n的数组求其中有几个长度为k的区间数字是连续的(无重复)
- Spring AOP 深入剖析
- OSChina 周日乱弹 —— 正确的撸串方式
- 第十三周项目一 动物怎么叫(抽象类)
- Foreign LINUX让你在Windows上运行Linux应用
- JSplitPane demo
- 3.SRS文档
- git add 详细介绍
- 探索核能利用的漫长之路
- MySQL 5.5.23半同步复制配置安装
- SpringMVC笔记
- 开始用Node.js编程
- 自定义实现InputFormat、OutputFormat、输出到多个文件目录中去、hadoop1.x api写单词计数的例子、运行时接收命令行参数,代码例子
- CentOS下安装配置Tomcat环境
- 从网易搬家到博客园
- java相关