hdu 4417 求[l,r]区间内小于v的有多少个

来源:互联网 发布:域名后缀biz什么意思 编辑:程序博客网 时间:2024/05/17 08:37
//hdu 4417 求[l,r]区间内小于v的有多少个////解题思路:////函数式线段树.终于见识了一下这个高大上的数据结构//当出现更新的时候将前面的线段树完整的保存下来,然后将//需要更新的节点复制下来的同时,将其不更新的部分连接到//前面一个线段树上.这样最省空间.并且多了一个性质,就是//两个线段树之间的对应节点满足加减性质.这样就很好啦~~//,记录每个数字出现的次数,再进行加减操作就好啦~~~////感悟:////很高大上的结构,看着还是挺简单,但是想法估计有点难//并且现在只是会裸地...继续加油吧!FIGHTING!!!#include <cstring>#include <algorithm>#include <iostream>#include <cstdio>#include <cmath>#include <string>#include <vector>#include <queue>#define For(x,a,b,c) for (int x = a; x <= b; x += c)#define Ffor(x,a,b,c) for (int x = a; x >= b; x -= c)#define cls(x,a) memset(x,a,sizeof(x))using namespace std;typedef long long ll;const double PI = acos(-1.0);const double eps = 1e-9;const int MAX_N = 1e5 + 8;const int INF = 1e9 + 7;const ll MOD = 1e9 + 7;int N,M;int a[MAX_N];int b[MAX_N];struct node{int ls;int rs;int sum;};struct IntravelTree{node p[MAX_N * 20];int root[MAX_N];int Siz;void init(){Siz = 1;}int build(int L,int R){int rt = Siz++;p[rt].sum = 0;if (L == R){return rt;}int M = (L + R) >> 1;p[rt].ls = build(L,M);p[rt].rs = build(M+1,R);return rt;}int update(int rt,int q,int v,int L,int R){int nrt = Siz++;p[nrt] = p[rt];p[nrt].sum += v;if (L == R) return nrt;int M = (L + R) >> 1;if (q <= M)p[nrt].ls = update(p[rt].ls,q,v,L,M);else p[nrt].rs = update(p[rt].rs,q,v,M+1,R);return nrt;}int query(int rtl,int rtr,int q,int L,int R){if (L == R) return p[rtr].sum - p[rtl].sum;int res = 0;int M = (L + R) >> 1;if (q <= M){res += query(p[rtl].ls,p[rtr].ls,q,L,M);}else {res += p[p[rtr].ls].sum - p[p[rtl].ls].sum;res += query(p[rtl].rs,p[rtr].rs,q,M+1,R);}return res;}}it;void input(){scanf("%d%d",&N,&M);For(i,1,N,1){scanf("%d",&a[i]);b[i] = a[i];}sort(b+1,b+N+1);int tot = unique(b + 1 , b + N + 1) - b;b[tot] = INF;it.init();it.root[0] = it.build(1,tot);For(i,1,N,1){a[i] = lower_bound(b + 1, b + tot + 1,a[i]) - b ;it.root[i] = it.update(it.root[i-1],a[i],1,1,tot);}//print();while(M--){int l,r,v;scanf("%d%d%d",&l,&r,&v);l++,r++;int k = upper_bound(b + 1,b + tot + 1, v) - b -1;//cout << k << endl;int ans = 0;if (k > 0){ans = it.query(it.root[l-1],it.root[r],k,1,tot);}printf("%d\n",ans);}}int main(){int t;//freopen("1.in","r",stdin);//freopen("1.out","w",stdout);scanf("%d",&t);int kase = 1;while(t--){printf("Case %d:\n",kase++);input();}}

0 0