您的位置:首页 > 其它

Super Mario(线段树离线区间k值)

2014-05-29 16:15 363 查看
以前见过这题,没做出来,知道是离线处理,这次仔细想了下,

首先把出现的高度都map离散化一下,以离散化出来的数目g建树,把每个位置都开俩个vector,一个存以这个位置为L的询问,一个存以这个位置为R的询问。

然后从1-g 进行更新,假如当前i是以第j个区间的开始位置,那么这时就可以询问一下<=p[j].h的个数s,显然这时第J个区间多加的,需要减掉,p[j].sum-=s;

然后更新第i个数,update(a[i],1,g,1);再找到某第k区间是以i结尾的,那么依旧询问一下,得出s,p[k].sum+=s;这样就是最终结果。

#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 200010
#define LL long long
#define INF 0xfffffff
const double eps = 1e-8;
const double pi = acos(-1.0);
const double inf = ~0u>>2;
int s[N<<2],a
,b
;
map<int,int>f;
vector<int>st
;
vector<int>ed
;
struct node
{
int l,r,h;
int sum;
}p
;
bool cmp(node a,node b)
{
if(a.l==b.l)
return a.r<b.r;
return a.l==b.l;
}
void up(int w)
{
s[w] = s[w<<1]+s[w<<1|1];
}
void build(int l,int r,int w)
{
if(l==r)
{
s[w] = 0;
return ;
}
int m = (l+r)>>1;
build(l,m,w<<1);
build(m+1,r,w<<1|1);
up(w);
}
void update(int p,int l,int r,int w)
{
if(l==r)
{
s[w] += 1;
return ;
}
int m = (l+r)>>1;
if(p<=m)
update(p,l,m,w<<1);
else
update(p,m+1,r,w<<1|1);
up(w);
}
int query(int a,int b,int l,int r,int w)
{
if(a<=l&&b>=r)
{
return s[w];
}
int m = (l+r)>>1;
int res =0;
if(a<=m)
res+=query(a,b,l,m,w<<1);
if(b>m)
res+=query(a,b,m+1,r,w<<1|1);
return res;
}
int main()
{
int t,n,q,i,j;
int kk = 0;
scanf("%d",&t);
while(t--)
{
int g = 0;
scanf("%d%d",&n,&q);
f.clear();
for(i = 1; i <= n; i++)
{
scanf("%d",&a[i]);
b[i] = a[i];
st[i].clear();
ed[i].clear();
}
for(i =1;i <= q ;i++)
{
scanf("%d%d%d",&p[i].l,&p[i].r,&p[i].h);
p[i].l++,p[i].r++;
p[i].sum = 0;
st[p[i].l].push_back(i);
ed[p[i].r].push_back(i);
a[n+i] = p[i].h;
}
sort(a,a+n+q+1);
f[a[1]] = ++g;
for(i = 2; i <= n+q ; i++)
{
if(a[i]!=a[i-1])
f[a[i]] = ++g;
}
build(1,g,1);
for(i = 1; i <= n ;i++)
{
if(st[i].size()!=0)
{
for(j = 0 ;j < st[i].size() ; j++)
{
int v = st[i][j];
int pre = query(1,f[p[v].h],1,g,1);
p[v].sum -= pre;
}
}
update(f[b[i]],1,g,1);
if(ed[i].size())
{
for(j = 0; j < ed[i].size() ;j++)
{
int v= ed[i][j];
int bef = query(1,f[p[v].h],1,g,1);
p[v].sum+=bef;
}
}
}
printf("Case %d:\n",++kk);
for(i = 1; i <= q ; i++)
{
printf("%d\n",p[i].sum);
}
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: