#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[N];
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( ̄ε ̄*)