HDU-4638 Group 树状数组+离线
2013-08-02 21:04
344 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4638
个人认为比较不错的题目。
题意:给一个1-n的排列,询问区间[l,r]的数排序后连续区间的个数。
对于这种题目容易想到对询问离线处理,难点是怎样在logn的时间内求出连续区间的个数。先对询问按右端点y从左到右排序,然后从左到右扫描整个数列,现在考虑加一个数num进去,如果我们前面存在num-1或者num+1,那么数列连续区间的个数是没有增加的,可能还会减少。因此我们可以维护一个数组数组或者线段树,对于每加进去的一个数num[i],对 i 点加1,如果 i 点前存在num[i]-1和num[i]+1,那么分别对他们所在的点-1。如果遇到询问,就求和就可以了。。。
个人认为比较不错的题目。
题意:给一个1-n的排列,询问区间[l,r]的数排序后连续区间的个数。
对于这种题目容易想到对询问离线处理,难点是怎样在logn的时间内求出连续区间的个数。先对询问按右端点y从左到右排序,然后从左到右扫描整个数列,现在考虑加一个数num进去,如果我们前面存在num-1或者num+1,那么数列连续区间的个数是没有增加的,可能还会减少。因此我们可以维护一个数组数组或者线段树,对于每加进去的一个数num[i],对 i 点加1,如果 i 点前存在num[i]-1和num[i]+1,那么分别对他们所在的点-1。如果遇到询问,就求和就可以了。。。
//STATUS:C++_AC_484MS_3364KB #include <functional> #include <algorithm> #include <iostream> //#include <ext/rope> #include <fstream> #include <sstream> #include <iomanip> #include <numeric> #include <cstring> #include <cassert> #include <cstdio> #include <string> #include <vector> #include <bitset> #include <queue> #include <stack> #include <cmath> #include <ctime> #include <list> #include <set> #include <map> using namespace std; //#pragma comment(linker,"/STACK:102400000,102400000") //using namespace __gnu_cxx; //define #define pii pair<int,int> #define mem(a,b) memset(a,b,sizeof(a)) #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define PI acos(-1.0) //typedef typedef __int64 LL; typedef unsigned __int64 ULL; //const const int N=100010; const int INF=0x3f3f3f3f; const int MOD=10007,STA=8000010; const LL LNF=1LL<<60; const double EPS=1e-8; const double OO=1e15; const int dx[4]={-1,0,1,0}; const int dy[4]={0,1,0,-1}; const int day[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; //Daily Use ... inline int sign(double x){return (x>EPS)-(x<-EPS);} template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;} template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;} template<class T> inline T lcm(T a,T b,T d){return a/d*b;} template<class T> inline T Min(T a,T b){return a<b?a:b;} template<class T> inline T Max(T a,T b){return a>b?a:b;} template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);} template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);} template<class T> inline T Min(T a,T b,T c,T d){return min(min(a, b),min(c,d));} template<class T> inline T Max(T a,T b,T c,T d){return max(max(a, b),max(c,d));} //End struct Node{ int x,y,id; bool operator <(const Node& a)const { return y<a.y; } }nod ; int num ,sum ,ans ,vis ,w ; int T,n,m; int lowbit(int x) { return x&(-x); } void update(int x,int val) { while(x<=n){ sum[x]+=val; x+=lowbit(x); } } int getsum(int x) { int ret=0; while(x){ ret+=sum[x]; x-=lowbit(x); } return ret; } int main(){ // freopen("in.txt","r",stdin); int i,j,k; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(i=1;i<=n;i++){ scanf("%d",&num[i]); w[num[i]]=i; } for(i=0;i<m;i++){ scanf("%d%d",&nod[i].x,&nod[i].y); nod[i].id=i; } sort(nod,nod+m); mem(sum,0);mem(vis,0); for(i=1,k=0;i<=n;i++){ update(i,1); if(vis[num[i]-1])update(w[num[i]-1],-1); if(vis[num[i]+1])update(w[num[i]+1],-1); vis[num[i]]=1; for(;nod[k].y==i && k<m;k++){ ans[nod[k].id]=getsum(nod[k].y)-getsum(nod[k].x-1); } if(k==m)break; } for(i=0;i<m;i++){ printf("%d\n",ans[i]); } } return 0; }
相关文章推荐
- HDU4638——Group(树状数组+离线操作)
- HDU 4638 Group(离线 + 树状数组)
- 离线处理(线段树|树状数组)| 莫对算法 —— HDU 4638 Group
- HDU 4638 Group (2013多校4 1007 离线处理+树状数组)
- hdu 4638 Group (莫队算法 || 离线线段树)
- hdu-4638-Group-(树状数组,离线操作)
- HDU 4638-Group(线段树+离线处理)
- HDU 4638 Group [离线+树状数组]
- hdu 4638 Group(离线线段树)
- hdu 4638 Group 树状数组
- HDU 4638 Group 多校第四场(线段树+离线询问)
- hdu 4638 Group(线段树,离线维护左边界,4级)
- hdu 4638 Group (线段树+离线处理)
- hdu 4638 Group(线段树,离线维护左边界,4级)
- hdu 4638 多校第四场 树状数组+离线处理
- HDU 4638 Group (线段树 + 离线)
- hdu 4638 Group (离线树状数组)
- hdu 4638 离线+树状数组
- Hduoj4638【树状数组+离线查询】
- HDU--3333(树状数组+离线处理)