HDU-4638 Group 树状数组+离线
题目链接: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 //STATUS:C++_AC_484MS_3364KB 2 #include <functional> 3 #include <algorithm> 4 #include <iostream> 5 //#include <ext/rope> 6 #include <fstream> 7 #include <sstream> 8 #include <iomanip> 9 #include <numeric> 10 #include <cstring> 11 #include <cassert> 12 #include <cstdio> 13 #include <string> 14 #include <vector> 15 #include <bitset> 16 #include <queue> 17 #include <stack> 18 #include <cmath> 19 #include <ctime> 20 #include <list> 21 #include <set> 22 #include <map> 23 using namespace std; 24 //#pragma comment(linker,"/STACK:102400000,102400000") 25 //using namespace __gnu_cxx; 26 //define 27 #define pii pair<int,int> 28 #define mem(a,b) memset(a,b,sizeof(a)) 29 #define lson l,mid,rt<<1 30 #define rson mid+1,r,rt<<1|1 31 #define PI acos(-1.0) 32 //typedef 33 typedef __int64 LL; 34 typedef unsigned __int64 ULL; 35 //const 36 const int N=100010; 37 const int INF=0x3f3f3f3f; 38 const int MOD=10007,STA=8000010; 39 const LL LNF=1LL<<60; 40 const double EPS=1e-8; 41 const double OO=1e15; 42 const int dx[4]={-1,0,1,0}; 43 const int dy[4]={0,1,0,-1}; 44 const int day[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; 45 //Daily Use ... 46 inline int sign(double x){return (x>EPS)-(x<-EPS);} 47 template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;} 48 template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;} 49 template<class T> inline T lcm(T a,T b,T d){return a/d*b;} 50 template<class T> inline T Min(T a,T b){return a<b?a:b;} 51 template<class T> inline T Max(T a,T b){return a>b?a:b;} 52 template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);} 53 template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);} 54 template<class T> inline T Min(T a,T b,T c,T d){return min(min(a, b),min(c,d));} 55 template<class T> inline T Max(T a,T b,T c,T d){return max(max(a, b),max(c,d));} 56 //End 57 58 struct Node{ 59 int x,y,id; 60 bool operator <(const Node& a)const { 61 return y<a.y; 62 } 63 }nod[N]; 64 65 int num[N],sum[N],ans[N],vis[N],w[N]; 66 int T,n,m; 67 68 int lowbit(int x) 69 { 70 return x&(-x); 71 } 72 73 void update(int x,int val) 74 { 75 while(x<=n){ 76 sum[x]+=val; 77 x+=lowbit(x); 78 } 79 } 80 81 int getsum(int x) 82 { 83 int ret=0; 84 while(x){ 85 ret+=sum[x]; 86 x-=lowbit(x); 87 } 88 return ret; 89 } 90 91 int main(){ 92 // freopen("in.txt","r",stdin); 93 int i,j,k; 94 scanf("%d",&T); 95 while(T--) 96 { 97 scanf("%d%d",&n,&m); 98 for(i=1;i<=n;i++){ 99 scanf("%d",&num[i]); 100 w[num[i]]=i; 101 } 102 for(i=0;i<m;i++){ 103 scanf("%d%d",&nod[i].x,&nod[i].y); 104 nod[i].id=i; 105 } 106 sort(nod,nod+m); 107 mem(sum,0);mem(vis,0); 108 for(i=1,k=0;i<=n;i++){ 109 update(i,1); 110 if(vis[num[i]-1])update(w[num[i]-1],-1); 111 if(vis[num[i]+1])update(w[num[i]+1],-1); 112 vis[num[i]]=1; 113 for(;nod[k].y==i && k<m;k++){ 114 ans[nod[k].id]=getsum(nod[k].y)-getsum(nod[k].x-1); 115 } 116 if(k==m)break; 117 } 118 119 for(i=0;i<m;i++){ 120 printf("%d\n",ans[i]); 121 } 122 } 123 return 0; 124 }