HDU 4417.Super Mario-無修改區間小於等於H的數的個數-可持久化線段樹
阿新 • • 發佈:2018-10-18
url java ios else string mes clu ber lower
Input
The first line follows an integer T, the number of test data.
For each test data:
The first line contains two integers n, m (1 <= n <=10^5, 1 <= m <= 10^5), n is the length of the road, m is the number of queries.
Next line contains n integers, the height of each brick, the range is [0, 1000000000].
Next m lines, each line contains three integers L, R,H.( 0 <= L <= R < n 0 <= H <= 1000000000.)
Sample Input
1
10 10
0 5 2 7 5 4 3 8 7 7
2 8 6
3 5 0
1 3 1
1 9 4
0 1 0
3 5 5
5 5 1
4 6 3
1 5 7
5 7 3
Super Mario
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 9618 Accepted Submission(s): 4074
For each test data:
The first line contains two integers n, m (1 <= n <=10^5, 1 <= m <= 10^5), n is the length of the road, m is the number of queries.
Next line contains n integers, the height of each brick, the range is [0, 1000000000].
Output For each case, output "Case X: " (X is the case number starting from 1) followed by m lines, each line contains an integer. The ith integer is the number of bricks Mario can hit for the ith query.
Sample Output Case 1: 4 0 0 3 1 2 0 1 5 1
Source 2012 ACM/ICPC Asia Regional Hangzhou Online 題意就是求區間小於等於H的數的個數。 這道題寫的時間有點長,錯在這幾個地方: (1)因為數是從0開始的,所以查詢的時候,區間l[i]和r[i]應該+1,查詢的時候就l[i]-1,r[i],或者區間l[i]和r[i]不變化,查詢的時候,就l[i],r[i]+1。 (2)因為查詢的是小於等於H的數,所以H也應該離散化,找對應的數,而不是直接查詢,這裏錯了好久才發現。 (3)數組開小了,杭電這道題數組開小了報的是WA,把maxn=1e5+10改成2e5+10就過了。 還有一點,其實是自己腦子不好特意測了一下。 因為數據已經離散化處理過了,所以查詢的時候不會有重復的數,所以查詢的時候,lower_bound()和upper_bound()都可以。
//int cnt=lower_bound(b+1,b+1+d,h[i])-b; int cnt=upper_bound(b+1,b+1+d,h[i])-b-1;
以上兩種都是對的。
代碼:
1 //無修改區間-可持久化線段樹(權值線段樹+可持久化) 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 #include<algorithm> 6 #include<bitset> 7 #include<cassert> 8 #include<cctype> 9 #include<cmath> 10 #include<cstdlib> 11 #include<ctime> 12 #include<deque> 13 #include<iomanip> 14 #include<list> 15 #include<map> 16 #include<queue> 17 #include<set> 18 #include<stack> 19 #include<vector> 20 using namespace std; 21 typedef long long ll; 22 typedef pair<int,int> pii; 23 24 const double PI=acos(-1.0); 25 const double eps=1e-6; 26 const ll mod=1e9+7; 27 const int inf=0x3f3f3f3f; 28 const int maxn=2e5+10; 29 const int maxm=100+10; 30 #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 31 #define lson l,m 32 #define rson m+1,r 33 34 int a[maxn],b[maxn],sum[maxn<<5],ls[maxn<<5],rs[maxn<<5];//sum線段樹裏保存的值,L左兒子,R右兒子 35 int n,m,sz=0; 36 37 void build(int &rt,int l,int r)//建棵空樹 38 { 39 rt=++sz;sum[rt]=0;//動態開點,初始值為0,空樹 40 if(l==r){ 41 return ; 42 } 43 44 int m=(l+r)>>1; 45 build(ls[rt],lson); 46 build(rs[rt],rson); 47 } 48 49 void update(int pre,int &rt,int l,int r,int p,int c) 50 { 51 rt=++sz;sum[rt]=sum[pre]+c;//插入序列,首先繼承以前的線段樹 然後直接單點+1就可以 52 ls[rt]=ls[pre];rs[rt]=rs[pre]; 53 if(l==r){ 54 return ; 55 } 56 57 int m=(l+r)>>1; 58 if(p<=m) update(ls[pre],ls[rt],lson,p,c);//因為右邊不需要更新,所以覆蓋掉左邊 59 else update(rs[pre],rs[rt],rson,p,c); 60 //sum[rt]=sum[ls[rt]]+sum[rs[rt]]; 61 } 62 63 int query(int pre,int rt,int L,int R,int l,int r)//查詢l到r區間就是第r次插入減去第l-1次插入後的線段樹的樣子 64 { 65 if(L>R) return 0; 66 if(L<=l&&r<=R){ 67 return sum[rt]-sum[pre]; 68 } 69 70 int ret=0; 71 int m=(l+r)>>1; 72 if(L<=m) ret+=query(ls[pre],ls[rt],L,R,lson); 73 if(R> m) ret+=query(rs[pre],rs[rt],L,R,rson); 74 return ret; 75 } 76 77 int rt[maxn],l[maxn],r[maxn],h[maxn]; 78 79 int main() 80 { 81 int t; 82 scanf("%d",&t); 83 for(int cas=1;cas<=t;cas++){ 84 scanf("%d%d",&n,&m); 85 sz=0; 86 for(int i=1;i<=n;i++) 87 { 88 scanf("%d",&a[i]); 89 b[i]=a[i]; 90 } 91 for(int i=1;i<=m;i++){ 92 scanf("%d%d%d",&l[i],&r[i],&h[i]); 93 b[i+n]=h[i]; 94 l[i]++,r[i]++; 95 } 96 sort(b+1,b+1+n+m);//首先把值全部排序去重,用於建權值線段樹,權值線段樹保存的內容是值的數量。 97 int d=unique(b+1,b+1+n+m)-(b+1); 98 build(rt[0],1,d); 99 for(int i=1;i<=n;i++) //按照序列順序插入值 100 { 101 int p=lower_bound(b+1,b+1+d,a[i])-b; 102 update(rt[i-1],rt[i],1,d,p,1); 103 } 104 printf("Case %d:\n",cas); 105 for(int i=1;i<=m;i++) 106 { 107 //int L=1,R=upper_bound(b+1,b+1+d,h)-b-1; 108 //int cnt=lower_bound(b+1,b+1+d,h[i])-b; 109 int cnt=upper_bound(b+1,b+1+d,h[i])-b-1; 110 //printf("%d\n",query(rt[l[i]],rt[r[i]+1],1,cnt,1,d)); 111 //printf("%d\n",query(rt[l],rt[r+1],1,cnt,1,d)); 112 printf("%d\n",query(rt[l[i]-1],rt[r[i]],1,cnt,1,d)); 113 } 114 } 115 return 0; 116 }
菜的難受。。。
HDU 4417.Super Mario-無修改區間小於等於H的數的個數-可持久化線段樹