hdu-1556-樹狀陣列-差分陣列
阿新 • • 發佈:2019-02-13
這題就是N個氣球每次對[a,b]區間的氣球塗色,每次詢問第i個氣球被塗了多少次色。
顯然樸素的樹狀陣列實現單點修改+區間求和
對於這題區間修改+單點查詢,思想延續樹狀陣列。加上差分陣列的思想很容易知道我們只需要用樹狀陣列維護一個差分陣列,每次修改區間[a,b],我們只需要
add(C[a],1) add(C[b+1],-1)
查詢單點值根據差分陣列的定義,就是求A[1,x]的和
關於差分陣列
對於序列a{},取a[i]-a[i-1]為其差分陣列b[i]的值,可以發現,a[i]=∑bj(1≤j≤i)
如 對於序列 a、b、c、d 其差分陣列為 a、 b-a、 c-b、 d-c
(a-0)
有a=a,b=a+(b-a),c=a+(b-a)+(c-b),d=a+(b-a)+(c-b)+(d-c)
對於區間[L,R],D陣列的修改再容易不過了
對於[L,R]中的元素,它們加上同樣的數,之間的差值不變,不必修改
唯一需要修改的就是D[L]=A[L]-A[L-1]和D[R+1]=A[R+1]-A[R]
因為A[L]改了A[L-1]沒改,A[R+1]沒改但A[R]改了,只有它們的差值改變了
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<math.h> #include<set> #include<vector> #include<sstream> #include<queue> #define PI 3.1415926535897932384626 #define inf 0x3f3f3f3f using namespace std; const int maxn=1e5+10; int a[maxn]; int main() { int n; while(scanf("%d",&n)!=EOF) { memset(a,0,sizeof(a)); if(n==0)break; for(int i=1;i<=n;i++){ int l,r; scanf("%d%d",&l,&r); a[l]++; a[r+1]--; } for(int i=2;i<=n;i++) { a[i]+=a[i-1]; } for(int i=1;i<=n;i++) if(i==1)cout<<a[i]; else cout<<" "<<a[i]; cout<<endl; } }
#include<cstdio> #include<string.h> #include<iostream> #include<algorithm> #include<math.h> using namespace std; const int maxn=1e5+10; int c[maxn]; int n; struct point { int x,y; }p[maxn]; int lowbit(int t) { return t&(-t); } void add(int i,int t) { while(i<=n) { c[i]+=t; i+=lowbit(i); } } int sum(int i) { int s=0; while(i>0) { s+=c[i]; i-=lowbit(i); } return s; } bool cmp(point a,point b) { if(a.y==b.y)return a.x<b.x; else return a.y>b.y; } int main() { //int n; while(cin>>n) { if(n==0)break; memset(p,0,sizeof(p)); memset(c,0,sizeof(c)); for(int i=1;i<=n;i++) { int a,b; scanf("%d%d",&a,&b); add(a,1); add(b+1,-1); } for(int i=1;i<n;i++) { printf("%d ",sum(i)); } printf("%d\n",sum(n)); } return 0; }