以前见过这题,没做出来,知道是离线处理,这次仔细想了下,

首先把出现的高度都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;这样就是最终结果。

Super Mario(线段树离线区间k值)_#includeSuper Mario(线段树离线区间k值)_离散化_02
  1 #include <iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<stdlib.h>
  6 #include<vector>
  7 #include<cmath>
  8 #include<queue>
  9 #include<set>
 10 #include<map>
 11 using namespace std;
 12 #define N 200010
 13 #define LL long long
 14 #define INF 0xfffffff
 15 const double eps = 1e-8;
 16 const double pi = acos(-1.0);
 17 const double inf = ~0u>>2;
 18 int s[N<<2],a[N],b[N];
 19 map<int,int>f;
 20 vector<int>st[N];
 21 vector<int>ed[N];
 22 struct node
 23 {
 24     int l,r,h;
 25     int sum;
 26 }p[N];
 27 bool cmp(node a,node b)
 28 {
 29     if(a.l==b.l)
 30     return a.r<b.r;
 31     return a.l==b.l;
 32 }
 33 void up(int w)
 34 {
 35     s[w] = s[w<<1]+s[w<<1|1];
 36 }
 37 void build(int l,int r,int w)
 38 {
 39     if(l==r)
 40     {
 41         s[w] = 0;
 42         return ;
 43     }
 44     int m = (l+r)>>1;
 45     build(l,m,w<<1);
 46     build(m+1,r,w<<1|1);
 47     up(w);
 48 }
 49 void update(int p,int l,int r,int w)
 50 {
 51     if(l==r)
 52     {
 53         s[w] += 1;
 54         return ;
 55     }
 56     int m = (l+r)>>1;
 57     if(p<=m)
 58     update(p,l,m,w<<1);
 59     else
 60     update(p,m+1,r,w<<1|1);
 61     up(w);
 62 }
 63 int query(int a,int b,int l,int r,int w)
 64 {
 65     if(a<=l&&b>=r)
 66     {
 67         return s[w];
 68     }
 69     int m = (l+r)>>1;
 70     int res =0;
 71     if(a<=m)
 72     res+=query(a,b,l,m,w<<1);
 73     if(b>m)
 74     res+=query(a,b,m+1,r,w<<1|1);
 75     return res;
 76 }
 77 int main()
 78 {
 79     int t,n,q,i,j;
 80     int kk = 0;
 81     scanf("%d",&t);
 82     while(t--)
 83     {
 84         int g = 0;
 85         scanf("%d%d",&n,&q);
 86         f.clear();
 87         for(i = 1; i <= n; i++)
 88         {
 89             scanf("%d",&a[i]);
 90             b[i] = a[i];
 91             st[i].clear();
 92             ed[i].clear();
 93         }
 94         for(i =1;i <= q ;i++)
 95         {
 96             scanf("%d%d%d",&p[i].l,&p[i].r,&p[i].h);
 97             p[i].l++,p[i].r++;
 98             p[i].sum = 0;
 99             st[p[i].l].push_back(i);
100             ed[p[i].r].push_back(i);
101             a[n+i] = p[i].h;
102         }
103         sort(a,a+n+q+1);
104         f[a[1]] = ++g;
105         for(i = 2; i <= n+q ; i++)
106         {
107             if(a[i]!=a[i-1])
108             f[a[i]] = ++g;
109         }
110         build(1,g,1);
111         for(i = 1; i <= n ;i++)
112         {
113             if(st[i].size()!=0)
114             {
115                 for(j = 0 ;j < st[i].size() ; j++)
116                 {
117                     int v = st[i][j];
118                     int pre = query(1,f[p[v].h],1,g,1);
119                     p[v].sum -= pre;
120                 }
121             }
122             update(f[b[i]],1,g,1);
123             if(ed[i].size())
124             {
125                 for(j = 0; j < ed[i].size() ;j++)
126                 {
127                     int v= ed[i][j];
128                     int bef = query(1,f[p[v].h],1,g,1);
129                     p[v].sum+=bef;
130                 }
131             }
132         }
133         printf("Case %d:\n",++kk);
134         for(i = 1; i <= q ; i++)
135         {
136             printf("%d\n",p[i].sum);
137         }
138     }
139     return 0;
140 }
View Code