线段树专题#2_蒟蒻训练历程记录_HDU5775
2016-07-29 15:34
393 查看
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
#include<stack>//线段树单点更新查询
using namespace std;
typedef long long ll;
#define N 100010
int g[4*N];
typedef struct A{
int w;
int pos1;
int add;
}A;
A a
;
bool cmp(A a, A b)
{
return a.w < b.w;
}
void init(int rt, int l , int r)//递归建立线段树
{
if(l == r)
{
g[rt] = 0;
return;
}
int mid = (l+r) >> 1;
init(rt<<1, l, mid);
init(rt<<1|1, mid+1, r);
g[rt] = 0;
}
int find(int rt, int l, int r, int L, int R)//递归查询
{
if(l >= L && r <= R)
{
return g[rt];
}
int k1 = 0, k2 = 0;
int mid = (l+r) >> 1;
if(mid >= L)//这个地方区间要跟所查询的总区间相比较而不是目前查询的区间
{
k1 = find(rt<<1, l, mid, L, R);
}
if(mid < R)
{
k2 = find(rt<<1|1, mid+1, r, L, R);
}
return k1+k2;
}
void update(int rt, int l, int r, int x)//要记住一直更新的都是现在的根节点。。
{
if(l == r && l == x)
{
g[rt]++;
return;
}
int mid = (l+r) >> 1;
if(x <= mid)//这回是拿查找的值跟mid作比较
{
update(rt<<1, l, mid, x);
g[rt]++;//这个地方更新错了。。
}
if(mid < x)
{
update(rt<<1|1, mid+1, r, x);
g[rt]++;
}
}
int main()
{
int t, num = 0;
scanf("%d", &t);
while(t--)
{
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++)
{
scanf("%d", &a[i].w);
a[i].pos1 = i;
}
init(1, 1, n);//初始化建树
for(int i = n; i >= 1; i--)
{
if(a[i].w == 1)
a[i].add = 0;
else
a[i].add = find(1, 1, n, 1, a[i].w-1);
update(1, 1, n, a[i].w);//不管是不是1都要更新啊。。
}
sort(a+1, a+n+1, cmp);
printf("Case #%d:", ++num);
for(int i = 1; i <= n; i++)
{
int t1 = min(a[i].pos1, i);
int t2 = a[i].pos1+a[i].add;
//printf("%d %d %d\n", i, a[i].pos1, a[i].add);
printf(" %d", t2-t1);
}
printf("\n");
}
return 0;
}
这道题楼主思路想对了,就是寻找数组中的一个元素前面比它大的个数和后面比它小的个数取最大值。可是比赛的时候完全没有想到用线段树来进行查询啊。。。于是生无可恋脸的磨完了比赛~啊啊太弱了好忧桑~还是好好训练吧~o( ̄ε ̄*)
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
#include<stack>//线段树单点更新查询
using namespace std;
typedef long long ll;
#define N 100010
int g[4*N];
typedef struct A{
int w;
int pos1;
int add;
}A;
A a
;
bool cmp(A a, A b)
{
return a.w < b.w;
}
void init(int rt, int l , int r)//递归建立线段树
{
if(l == r)
{
g[rt] = 0;
return;
}
int mid = (l+r) >> 1;
init(rt<<1, l, mid);
init(rt<<1|1, mid+1, r);
g[rt] = 0;
}
int find(int rt, int l, int r, int L, int R)//递归查询
{
if(l >= L && r <= R)
{
return g[rt];
}
int k1 = 0, k2 = 0;
int mid = (l+r) >> 1;
if(mid >= L)//这个地方区间要跟所查询的总区间相比较而不是目前查询的区间
{
k1 = find(rt<<1, l, mid, L, R);
}
if(mid < R)
{
k2 = find(rt<<1|1, mid+1, r, L, R);
}
return k1+k2;
}
void update(int rt, int l, int r, int x)//要记住一直更新的都是现在的根节点。。
{
if(l == r && l == x)
{
g[rt]++;
return;
}
int mid = (l+r) >> 1;
if(x <= mid)//这回是拿查找的值跟mid作比较
{
update(rt<<1, l, mid, x);
g[rt]++;//这个地方更新错了。。
}
if(mid < x)
{
update(rt<<1|1, mid+1, r, x);
g[rt]++;
}
}
int main()
{
int t, num = 0;
scanf("%d", &t);
while(t--)
{
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++)
{
scanf("%d", &a[i].w);
a[i].pos1 = i;
}
init(1, 1, n);//初始化建树
for(int i = n; i >= 1; i--)
{
if(a[i].w == 1)
a[i].add = 0;
else
a[i].add = find(1, 1, n, 1, a[i].w-1);
update(1, 1, n, a[i].w);//不管是不是1都要更新啊。。
}
sort(a+1, a+n+1, cmp);
printf("Case #%d:", ++num);
for(int i = 1; i <= n; i++)
{
int t1 = min(a[i].pos1, i);
int t2 = a[i].pos1+a[i].add;
//printf("%d %d %d\n", i, a[i].pos1, a[i].add);
printf(" %d", t2-t1);
}
printf("\n");
}
return 0;
}
这道题楼主思路想对了,就是寻找数组中的一个元素前面比它大的个数和后面比它小的个数取最大值。可是比赛的时候完全没有想到用线段树来进行查询啊。。。于是生无可恋脸的磨完了比赛~啊啊太弱了好忧桑~还是好好训练吧~o( ̄ε ̄*)
相关文章推荐
- 简单的四则运算
- 数的奇偶性
- ACMer博客瀑布流分析
- ACM程序设计大赛题目分类
- 2015年acm国内排名
- 计算字符串最后一个单词长度
- ACM网址
- 1272 小希的迷宫
- 1272 小希的迷宫
- hdu 1250 大数相加并用数组储存
- 矩阵的乘法操作
- 蚂蚁爬行问题
- 蚂蚁爬行问题
- 求两个数的最大公约数【ACM基础题】
- 打印出二进制中所有1的位置
- 杭电题目---一只小蜜蜂
- HDOJ 1002 A + B Problem II (Big Numbers Addition)
- 初学ACM - 半数集(Half Set)问题 NOJ 1010 / FOJ 1207
- 初学ACM - 组合数学基础题目PKU 1833
- 线段树题集