hdu5592 线段树
2015-12-06 00:58
330 查看
链接http://acm.hdu.edu.cn/showproblem.php?pid=5592
Accepts: 218
Submissions: 983
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 131072/131072 K (Java/Others)
问题描述
输入描述
输出描述
输入样例
输出样例
先倒着来一次a[i] -= a[i-1],然后倒着来一次,i-a[i]就是第i个数在集合中的名次,算出之后从集合里删除掉这个元素,不用平衡树,用树桩数组和线段树也能做,简单的区间第k大类似。
#include <iostream>
#include <cstdio>
#include <map>
#define lc(o) (o<<1)
#define rc(o) (o<<1|1)
typedef long long ll;
const int maxn = 5e4+10;
using namespace std;
int a[maxn],b[maxn];
int sum[maxn<<4];
void built(int o,int L,int R)
{
if(L==R) {
sum[o] = 1;
return ;
}
int m = (L+R)>>1;
built(lc(o),L,m);
built(rc(o),m+1,R);
sum[o] = sum[lc(o)]+sum[rc(o)];
}
void Modify(int o,int L,int R,int x)
{
if(L==R) {
sum[o] = 0;
return;
}
int m = (L+R)>>1;
if(x <= m) Modify(lc(o),L,m,x);
else Modify(rc(o),m+1,R,x);
sum[o] = sum[lc(o)]+sum[rc(o)];
}
int Query(int o,int L,int R,int s)
{
if(L == R) return L;
int m = (L+R)>>1;
if(sum[lc(o)] >= s) return Query(lc(o),L,m,s);
return Query(rc(o),m+1,R,s-sum[lc(o)]);
}
int main()
{
int T;scanf("%d",&T);
while(T--) {
int n;scanf("%d",&n);
for(int i = 1; i <= n; ++i) {
scanf("%d",a+i);
}
built(1,1,n);
for(int i = n; i > 1; --i) a[i] -= a[i-1];
for(int i = n; i >= 1; --i) {
int x = i-a[i];
b[i] = Query(1,1,n,x);
Modify(1,1,n,b[i]);
}
for(int i = 1; i <= n; ++i) printf("%d%c",b[i]," \n"[i==n]);
}
return 0;
}
ZYB's Premutation
Accepts: 218
Submissions: 983
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 131072/131072 K (Java/Others)
问题描述
ZYBZYB有一个排列PP,但他只记得PP中每个前缀区间的逆序对数,现在他要求你还原这个排列. (i,j)(i < j)(i,j)(i<j)被称为一对逆序对当且仅当A_i>A_jAi>Aj
输入描述
第一行一个整数TT表示数据组数。 接下来每组数据: 第一行一个正整数NN,描述排列的长度. 第二行NN个正整数A_iAi,描述前缀区间[1,i][1,i]的逆序对数. 数据保证合法. 1 \leq T \leq 51≤T≤5,1 \leq N \leq 500001≤N≤50000
输出描述
TT行每行NN个整数表示答案的排列.
输入样例
1 3 0 1 2
输出样例
3 1 2
先倒着来一次a[i] -= a[i-1],然后倒着来一次,i-a[i]就是第i个数在集合中的名次,算出之后从集合里删除掉这个元素,不用平衡树,用树桩数组和线段树也能做,简单的区间第k大类似。
#include <iostream>
#include <cstdio>
#include <map>
#define lc(o) (o<<1)
#define rc(o) (o<<1|1)
typedef long long ll;
const int maxn = 5e4+10;
using namespace std;
int a[maxn],b[maxn];
int sum[maxn<<4];
void built(int o,int L,int R)
{
if(L==R) {
sum[o] = 1;
return ;
}
int m = (L+R)>>1;
built(lc(o),L,m);
built(rc(o),m+1,R);
sum[o] = sum[lc(o)]+sum[rc(o)];
}
void Modify(int o,int L,int R,int x)
{
if(L==R) {
sum[o] = 0;
return;
}
int m = (L+R)>>1;
if(x <= m) Modify(lc(o),L,m,x);
else Modify(rc(o),m+1,R,x);
sum[o] = sum[lc(o)]+sum[rc(o)];
}
int Query(int o,int L,int R,int s)
{
if(L == R) return L;
int m = (L+R)>>1;
if(sum[lc(o)] >= s) return Query(lc(o),L,m,s);
return Query(rc(o),m+1,R,s-sum[lc(o)]);
}
int main()
{
int T;scanf("%d",&T);
while(T--) {
int n;scanf("%d",&n);
for(int i = 1; i <= n; ++i) {
scanf("%d",a+i);
}
built(1,1,n);
for(int i = n; i > 1; --i) a[i] -= a[i-1];
for(int i = n; i >= 1; --i) {
int x = i-a[i];
b[i] = Query(1,1,n,x);
Modify(1,1,n,b[i]);
}
for(int i = 1; i <= n; ++i) printf("%d%c",b[i]," \n"[i==n]);
}
return 0;
}
相关文章推荐
- 逆序对
- 线段树题集
- 插入排序移动次数
- hdu1754
- HDU1394
- 敌兵布阵 (1)
- I Hate It (1)
- LCIS (2)
- A Simple Problem with Integers (2)
- Mayor's posters (3)
- Buy Tickets (3)
- 归并排序-逆序对的求解
- Codeforces Coder-Strike 2014 - Finals (online edition, Div. 1)
- 线段树
- UVA - 12532 Interval Product
- HDU 1166 敌兵布阵
- POJ 2352 Stars
- POJ 3264 Balanced Lineup
- hdu 1542 求矩形并的面积
- 关于数据结构之线段树