有一点类似区间K值的求法。

这里有两颗树,一个是自己建的线段树,一个是题目中给定的树。以线段树和树进行区分。

首先离散化一下,以离散化后的结果建线段树,线段树的节点开了2维,一维保存当前以当前节点为权值的树的节点是往左走的,另一维是往右走的,用一个vector保存一下以当前i节点为结束的询问,因为所有的询问都是从根节点出发的,只需保存终点即可。

然后从根节点出发遍历整棵树,当走到当前节点时,枚举以当前节点的询问q[i],然后求出比q[i].x大的向左和向右走的节点个数,以及比它小的个数,如果有相等的直接为0,最后根据可能性加起来即可。

每走完一个节点,回退时,把当前节点更新为未走。

把树节点的权值跟询问的搞混了,WA一次。。搞了组数据才看出来

 #include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stdlib.h>
#include<vector>
#include<cmath>
#include<queue>
#include<set>
#include<map>
using namespace std;
#define N 100010
#define LL long long
#define INF 0xfffffff
const double eps = 1e-;
const double pi = acos(-1.0);
const double inf = ~0u>>;
#pragma comment(linker, "/STACK:1024000000,1024000000")
int s[N<<][],a[N<<],b[N];
map<int,int>f;
vector<int>ed[N];//儿子
vector<int>dd[N];//以i节点结束的询问
int g ;
struct node{
int v,x;
int ax,ay,f;
}p[N];
void up(int w)
{
s[w][] = s[w<<][]+s[w<<|][];//向左走
s[w][] = s[w<<][]+s[w<<|][];//向右走
}
void build(int l,int r,int w)
{
if(l==r)
{
s[w][] = s[w][] = ;
return ;
}
int m = (l+r)>>;
build(l,m,w<<);
build(m+,r,w<<|);
up(w);
}
void update(int p,int d,int dir,int l,int r,int w)
{
if(l==r)
{
s[w][dir] += d;
return ;
}
int m = (l+r)>>;
if(p<=m) update(p,d,dir,l,m,w<<);
else update(p,d,dir,m+,r,w<<|);
up(w);
}
int query(int a,int b,int dir,int l,int r,int w)
{
if(a<=l&&b>=r)
{
return s[w][dir];
}
int m = (l+r)>>;
int res=;
if(a<=m) res+=query(a,b,dir,l,m,w<<);
if(b>m) res+=query(a,b,dir,m+,r,w<<|);
return res;
}
void dfs(int u,int pre)
{
int i;
for(i = ; i < dd[u].size(); i++)
{
int k = dd[u][i];
int id = f[p[k].x];
// cout<<k<<endl;
int cnt1 = query(id,id,,,g,);
int cnt2 = query(id,id,,,g,);
//cout<<cnt1<<" "<<cnt2<<" "<<u<<" "<<id<<endl;
if(cnt1||cnt2)
{
p[k].f = ;
continue;
}
else
{
p[k].f = ;
int l0 = query(,id,,,g,);
int l1 = query(,id,,,g,);
int r0 = query(id,g,,,g,);
int r1 = query(id,g,,,g,);
// cout<<l0<<" "<<l1<<" "<<r0<<" "<<r1<<endl;
p[k].ay = r0+r1+*(l1+l0);
p[k].ax = l1;
}
}
for(i = ;i < ed[u].size() ; i++)
{
int v = ed[u][i];
int id = f[b[u]];
// cout<<id<<" "<<u<<endl;
if(i==)
{
update(id,,,,g,);
}
else update(id,,,,g,);
dfs(v,u);
if(i==)
update(id,-,,,g,);
else update(id,-,,,g,);
}
}
int main()
{
int t,i,n,m,q;
cin>>t;
while(t--)
{
scanf("%d",&n);
f.clear();
g = ;
for(i = ; i <=n; i++)
{
scanf("%d",&a[i]);
b[i] = a[i];
ed[i].clear();
dd[i].clear();
}
scanf("%d",&m);
for(i = ; i <= m; i++)
{
int u,l,r;
scanf("%d%d%d",&u,&l,&r);
ed[u].push_back(l);
ed[u].push_back(r);
}
scanf("%d",&q);
for(i = ;i <= q ;i++)
{
scanf("%d%d",&p[i].v,&p[i].x);
dd[p[i].v].push_back(i);
a[n+i] = p[i].x;
}
sort(a+,a+n+q+);
f[a[]] = ++g;
for(i = ; i <= n+q ; i++)
{
if(a[i]!=a[i-])
f[a[i]] = ++g;
}
build(,g,);
dfs(,-);
for(i = ; i <= q; i++)
{
if(p[i].f==)
printf("%d\n",);
else
printf("%d %d\n",p[i].ax,p[i].ay);
}
}
return ;
}

Partition(线段树的离线处理)的更多相关文章

  1. Codeforces1110F Nearest Leaf dfs + 线段树 + 询问离线

    Codeforces1110F dfs + 线段树 + 询问离线 F. Nearest Leaf Description: Let's define the Eulerian traversal of ...

  2. HDU 3874 Necklace (树状数组 | 线段树 的离线处理)

    Necklace Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total S ...

  3. CF803G - Periodic RMQ Problem 动态开点线段树 或 离线

    CF 题意 有一个长度为n × k (<=1E9)的数组,有区间修改和区间查询最小值的操作. 思路 由于数组过大,直接做显然不行. 有两种做法,可以用动态开点版本的线段树,或者离线搞(还没搞)( ...

  4. NOIP2012借教室[线段树|离线 差分 二分答案]

    题目描述 在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要 向学校申请借教室.教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样. 面对海量租借教室的信息,我们自 ...

  5. HDU 4288 Coder 【线段树+离线处理+离散化】

    题意略. 离线处理,离散化.然后就是简单的线段树了.需要根据mod 5的值来维护.具体看代码了. /* 线段树+离散化+离线处理 */ #include <cstdio> #include ...

  6. E - No Pain No Game 线段树 离线处理 区间排序

    E - No Pain No Game  HDU - 4630 这个题目很好,以后可以再写写.这个题目就是线段树的离线写法,推荐一个博客:https://blog.csdn.net/u01003321 ...

  7. 【luogu3733】【HAOI2017】 八纵八横 (线段树分治+线性基)

    Descroption 原题链接 给你一个\(n\)个点的图,有重边有自环保证连通,最开始有\(m\)条固定的边,要求你支持加边删边改边(均不涉及最初的\(m\)条边),每一次操作都求出图中经过\(1 ...

  8. 2019.01.13 bzoj4137: [FJOI2015]火星商店问题(线段树分治+可持久化01trie)

    传送门 题意:序列上有nnn个商店,有两种事件会发生: sss商店上进购标价为vvv的一个物品 求编号为[l,r][l,r][l,r]之间的位置买ddd天内新进购的所有物品与一个数xxx异或值的最大值 ...

  9. 洛谷T44252 线索_分治线段树_思维题

    分治线段树,其实就是将标记永久化,到最后再统一下传所有标记. 至于先后顺序,可以给每个节点开一个时间戳. 一般地,分治线段树用于离线,只查询一次答案的题目. 本题中,标记要被下传 222 次. Cod ...

随机推荐

  1. 字符编码乱码问题(servlet底层 编码大揭秘)

    好多初学者会遇到,请求过去的信息内包含中文(一般会是get方式提交过去的请求会出现).好郁闷,这是为什么呢.有下面分析下,说的不好可以吐槽 话说我们能遇到这种编码的问题,归根结底就是这  这 web开 ...

  2. 201621123007 Java程序设计第一周 学习总结

    第一周-Java基本概念 201621123007 <Java程序设计> 第一周学习总结 1. 本周学习总结 java是面向对象的一类语言,三大特征:封装性,继承性,多态性. jdk jr ...

  3. [LeetCode] Longest Valid Parentheses -- 挂动态规划羊头卖stack的狗肉

    (Version 1.3) 这题在LeetCode上的标签比较有欺骗性,虽然标签写着有DP,但是实际上根本不需要使用动态规划,相反的,使用动态规划反而会在LeetCode OJ上面超时.这题正确的做法 ...

  4. Snmp在Windows下的实现----WinSNMP编程原理

    在Windows 下实现SNMP协议的编程,可以采用Winsock接口,在161,162端口通过udp传送信息.在Windows 2000中,Microsoft已经封装了SNMP协议的实现,提供了一套 ...

  5. APACHE2 服务器配置 (一)

    1.安装 sudo apt-get install apache2 2.重启: sudo service apache2 resatrt 3.设置根目录: /var/www 设置方法: 2.2版: / ...

  6. 是否要从单片机转为嵌入式Linux?

    作者:嵌入式老鸟火哥 授权转载于公众号嵌入式老鸟的职场之道(ID: ict_embedded),有增加内容和修改. 最近很多童鞋投票并咨询如何从单片机转为嵌入式Linux开发.看来读者圈中做单片机,R ...

  7. TModJS:使用tmodjs

    ylbtech-TModJS:使用tmodjs 1.返回顶部 1. 1.安装 npm install -g tmodjs 2.配置 我的模板都放在tpl文件夹中,htmls用于存放模板页面,每一个后缀 ...

  8. 五、怎样修改oracle某个用户的密码

    1.键入命令:sqlplus / as sysdba 2.在sqlplus窗口执行命令: alter user you_username identified by you_password;

  9. Mike and distribution

    题意: 给定 $n$ 个物品,每个物品有两个属性$a_i$, $b_i$,求一个长度为$[\frac{n}{2}]+1$的子序列 $p$ 使得 $2 * \sum_{i = 1}^{|p|}{a_{p ...

  10. 性能测试之Jmeter学习(三)

    一.Jmeter执行顺序规则: 元件执行顺序的规则很简单,在同一作用域名范围内,测试计划中的元件按照如下顺序执行. (1)配置元件(config elements ) (2)前置处理程序(Per-pr ...