牛客網NowCoder 2018年全國多校算法寒假訓練營練習比賽(第五場)A.逆序數 B.Big Water Problem(線段樹-區間查詢求和和單點更新) F.The Biggest Water Problem H.Tree Recovery(線段樹-區間查詢求和和區間更新)
阿新 • • 發佈:2018-03-06
numbers col 如果 -o img 數組 數據 .html log
空間限制:C/C++ 131072K,其他語言262144K
64bit IO Format: %lld
鏈接:https://www.nowcoder.com/acm/contest/77/A
來源:牛客網
B.Big Water Problem 時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 131072K,其他語言262144K
64bit IO Format: %lld
鏈接:https://www.nowcoder.com/acm/contest/77/B
來源:牛客網
空間限制:C/C++ 32768K,其他語言65536K
64bit IO Format: %lld
鏈接:https://www.nowcoder.com/acm/contest/77/F
來源:牛客網
空間限制:C/C++ 131072K,其他語言262144K
64bit IO Format: %lld
鏈接:https://www.nowcoder.com/acm/contest/77/H
來源:牛客網
隨便補了幾道題,可能也就能寫出來這幾道吧。最近被搜索虐爆了,要抓緊去看搜索,隨便寫寫就溜,備忘一下線段樹新的板子(以前的不好用,太垃圾了)
空間限制:C/C++ 131072K,其他語言262144K
64bit IO Format: %lld
鏈接:https://www.nowcoder.com/acm/contest/77/A
來源:牛客網
題目描述
在一個排列中,如果一對數的前後位置與大小順序相反,即前面的數大於後面的數,那麽它們就稱為一個逆序。一個排列中逆序的總數就稱為這個排列的逆序數。比如一個序列為4 5 1 3 2, 那麽這個序列的逆序數為7,逆序對分別為(4, 1), (4, 3), (4, 2), (5, 1), (5, 3), (5, 2),(3, 2)。輸入描述:
第一行有一個整數n(1 <= n <= 100000), 然後第二行跟著n個整數,對於第i個數a[i],(0 <= a[i] <= 100000)。
輸出描述:
輸出這個序列中的逆序數示例1
輸入
5 4 5 1 3 2
輸出
7這道題目就是找每個數的貢獻就可以。 代碼:
1 //A 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8#include<map> 9 using namespace std; 10 typedef long long ll; 11 const int maxn=1e5+10; 12 int a[maxn]; 13 int main(){ 14 int n,m; 15 ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 16 cin>>n; 17 ll ans=0; 18 for(int i=0;i<n;i++){ 19 cin>>m; 20 ans+=a[m];21 for(int j=0;j<m;j++) 22 a[j]++; 23 } 24 cout<<ans<<endl; 25 }
B.Big Water Problem 時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 131072K,其他語言262144K
64bit IO Format: %lld
鏈接:https://www.nowcoder.com/acm/contest/77/B
來源:牛客網
題目描述
給一個數列,會有多次詢問,對於每一次詢問,會有兩種操作: 1:給定兩個整數x, y, 然後在原數組的第x位置上加y; 2:給定兩個整數l,r,然後輸出數組從第l位加到第r位數字的和並換行輸入描述:
第一行有兩個整數n, m(1 <= n, m <= 100000)代表數列的長度和詢問的次數
第二行n個數字,對於第i個數字a[i],(0<=a[i]<=100000)。
接下來m行,每一行有三個整數f, x, y。第一個整數f是1或者是2,代表操作類型,如果是1,接下來兩個數x,y代表第x的位置上加y,如果是2,則求x到y的和,保證數據合法。
輸出描述:
輸出每次求和的結果並換行示例1
輸入
10 2 1 2 3 4 5 6 7 8 9 10 1 1 9 2 1 10
輸出
64
這個題就是線段樹的區間查詢求和和單點更新。
傳送3篇寫的可以的線段樹的博客,看完就會了(大一學的,沒怎麽用,就忘了,還要重新看。。。)
1.基礎基礎 2.繼續繼續 3.總結總結
代碼:
1 //B-線段樹-區間查詢求和和單點更新 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 #include<cstdlib> 6 #include<algorithm> 7 using namespace std; 8 typedef long long ll; 9 #define ls l,m,rt<<1 10 #define rs m+1,r,rt<<1|1 11 #define root 1,n,1 12 const int maxn=1e5+10; 13 ll Sum[maxn<<2],Add[maxn<<2];//Sum為求和,Add為懶惰標記 14 ll A[maxn],n;//存原數組數據下標 15 16 //PushUp函數更新節點信息,這裏是求和 17 void PushUp(int rt){ 18 Sum[rt]=Sum[rt<<1]+Sum[rt<<1|1]; 19 } 20 21 //下推標記的函數 22 void PushDown(int rt,int m){ 23 if(Add[rt]){//下推標記 24 Add[rt<<1]+=Add[rt]; 25 Add[rt<<1|1]+=Add[rt]; 26 Sum[rt<<1]+=Add[rt]*(m-(m>>1)); 27 Sum[rt<<1|1]+=Add[rt]*(m>>1); 28 Add[rt]=0;//清除本節點標記 29 } 30 } 31 32 //建樹 33 void Build(int l,int r,int rt){//rt表示當前節點編號 34 Add[rt]=0; 35 if(l==r){ 36 Sum[rt]=A[l];return; 37 } 38 int m=(l+r)>>1; 39 Build(ls); 40 Build(rs); 41 PushUp(rt); 42 } 43 44 //區間修改A[L,R]+=C 45 //void Update(int L,int R,int C,int l,int r,int rt){ 46 // if(L<=l&&r<=R){ 47 // Sum[rt]+=(ll)C*(r-l+1); 48 // Add[rt]+=C; 49 // return ; 50 // } 51 // PushDown(rt,r-l+1);//下推標記 52 // int m=(l+r)>>1; 53 // if(L<=m)Update(L,R,C,ls); 54 // if(R>m)Update(L,R,C,rs); 55 // PushUp(rt);//更新本節點 56 //} 57 58 //點修改A[L]+=C 59 void Update(int L,int C,int l,int r,int rt){ 60 if(l==r){ 61 Sum[rt]+=C; 62 return ; 63 } 64 int m=(l+r)>>1; 65 if(L<=m)Update(L,C,ls); 66 else Update(L,C,rs); 67 PushUp(rt); 68 } 69 70 //區間查詢A[L,R]的和 71 int Query(int L,int R,int l,int r,int rt){ 72 if(L<=l&&r<=R){ 73 return Sum[rt]; 74 } 75 PushDown(rt,r-l+1);//下推標記,否則Sum可能不正確 76 int m=(l+r)>>1; 77 ll ANS=0;//累計答案 78 if(L<=m)ANS+=Query(L,R,ls); 79 if(R>m)ANS+=Query(L,R,rs); 80 return ANS; 81 } 82 83 int main(){ 84 int n,m; 85 scanf("%d%d",&n,&m); 86 for(int i=1;i<=n;i++) 87 scanf("%lld",&A[i]); 88 Build(1,n,1);//建樹 89 while(m--){ 90 int x; 91 scanf("%d",&x); 92 if(x==2){ 93 int a,b; 94 scanf("%d%d",&a,&b); 95 ll ANS=Query(a,b,root);//區間查詢 96 printf("%lld\n",ANS); 97 } 98 else{ 99 int a,C; 100 scanf("%d%d",&a,&C); 101 Update(a,C,root);//區間修改 102 } 103 } 104 return 0; 105 }
F.The Biggest Water Problem 時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 32768K,其他語言65536K
64bit IO Format: %lld
鏈接:https://www.nowcoder.com/acm/contest/77/F
來源:牛客網
題目描述
給你一個數,讓他進行巴啦啦能量,沙魯沙魯,小魔仙大變身,如果進行變身的數不滿足條件的話,就繼續讓他變身。。。直到滿足條件為止。 巴啦啦能量,沙魯沙魯,小魔仙大變身:對於一個數,把他所有位上的數字進行加和,得到新的數。 如果這個數字是個位數的話,那麽他就滿足條件。輸入描述:
給一個整數數字n(1<=n<=1e9)。
輸出描述:
輸出由n經過操作滿足條件的數示例1
輸入
12
輸出
3
說明
12 -> 1 + 2 = 3示例2
輸入
38
輸出
2
說明
38 -> 3 + 8 = 11 -> 1 + 1 = 2
這個題本來還想偷一下懶,用itoa函數寫,但是我發現交上去測評姬報錯,可能是不支持吧。自己手寫了一個。
關於itoa,以前寫過備忘:我是智障
代碼:
1 //F 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 #include<algorithm> 6 #include<cmath> 7 #include<queue> 8 using namespace std; 9 const int maxn=100; 10 int a[maxn]; 11 int len; 12 void itoa(int n){ 13 len=0; 14 memset(a,0,sizeof(a)); 15 while(n){ 16 a[len++]=n%10; 17 n/=10; 18 } 19 } 20 int main(){ 21 int n; 22 ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 23 cin>>n; 24 itoa(n); 25 int tmp=0; 26 for(int i=0;i<len;i++) 27 tmp+=a[i]; 28 while(1){ 29 if(tmp>10){ 30 itoa(tmp); 31 tmp=0; 32 for(int i=0;i<len;i++) 33 tmp+=a[i]; 34 } 35 else { 36 cout<<tmp<<endl;break; 37 } 38 } 39 }
H.Tree Recovery 時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 131072K,其他語言262144K
64bit IO Format: %lld
鏈接:https://www.nowcoder.com/acm/contest/77/H
來源:牛客網
題目描述
You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.輸入描述:
輸出描述:
You need to answer all Q commands in order. One answer in a line.示例1
輸入
10 5 1 2 3 4 5 6 7 8 9 10 Q 4 4 Q 1 10 Q 2 4 C 3 6 3 Q 2 4
輸出
4 55 9 15
這個題是線段樹區間查詢求和和區間更新。
代碼:
1 /* 2 //H-線段樹-區間查詢求和和區間更新 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cstdlib> 7 #include<algorithm> 8 using namespace std; 9 typedef long long ll; 10 #define ls l,m,rt<<1 11 #define rs m+1,r,rt<<1|1 12 #define root 1,n,1 13 const int maxn=1e5+10; 14 ll Sum[maxn<<2],Add[maxn<<2];//Sum為求和,Add為懶惰標記 15 ll A[maxn],n;//存原數組數據下標 16 17 //PushUp函數更新節點信息,這裏是求和 18 void PushUp(int rt){ 19 Sum[rt]=Sum[rt<<1]+Sum[rt<<1|1]; 20 } 21 22 //下推標記的函數 23 void PushDown(int rt,int m){ 24 if(Add[rt]){//下推標記 25 Add[rt<<1]+=Add[rt]; 26 Add[rt<<1|1]+=Add[rt]; 27 Sum[rt<<1]+=Add[rt]*(m-(m>>1)); 28 Sum[rt<<1|1]+=Add[rt]*(m>>1); 29 Add[rt]=0;//清除本節點標記 30 } 31 } 32 33 //建樹 34 void Build(int l,int r,int rt){//rt表示當前節點編號 35 Add[rt]=0; 36 if(l==r){ 37 Sum[rt]=A[l];return; 38 } 39 int m=(l+r)>>1; 40 Build(ls); 41 Build(rs); 42 PushUp(rt); 43 } 44 45 //區間修改A[L,R]+=C 46 void Update(int L,int R,int C,int l,int r,int rt){ 47 if(L<=l&&r<=R){ 48 Sum[rt]+=(ll)C*(r-l+1); 49 Add[rt]+=C; 50 return ; 51 } 52 PushDown(rt,r-l+1);//下推標記 53 int m=(l+r)>>1; 54 if(L<=m)Update(L,R,C,ls); 55 if(R>m)Update(L,R,C,rs); 56 PushUp(rt);//更新本節點 57 } 58 59 //區間查詢A[L,R]的和 60 int Query(int L,int R,int l,int r,int rt){ 61 if(L<=l&&r<=R){ 62 return Sum[rt]; 63 } 64 PushDown(rt,r-l+1);//下推標記,否則Sum可能不正確 65 int m=(l+r)>>1; 66 ll ANS=0;//累計答案 67 if(L<=m)ANS+=Query(L,R,ls); 68 if(R>m)ANS+=Query(L,R,rs); 69 return ANS; 70 } 71 72 int main(){ 73 int n,m; 74 scanf("%d%d",&n,&m); 75 for(int i=1;i<=n;i++) 76 scanf("%lld",&A[i]); 77 Build(1,n,1);//建樹 78 while(m--){ 79 char str[2]; 80 scanf("%s",str); 81 if(str[0]==‘Q‘){ 82 int a,b; 83 scanf("%d%d",&a,&b); 84 ll ANS=Query(a,b,root);//區間查詢 85 printf("%lld\n",ANS); 86 } 87 else{ 88 int a,b,C; 89 scanf("%d%d%d",&a,&b,&C); 90 Update(a,b,C,root);//區間修改 91 } 92 } 93 return 0; 94 } 95 */ 96 /* 97 樣例 98 10 5 99 1 2 3 4 5 6 7 8 9 10 100 Q 4 4 101 Q 1 10 102 Q 2 4 103 C 3 6 3 104 Q 2 4 105 */
就這樣,還有二位線段樹,還沒寫,以後寫。
滾去看搜索了,簡直被虐爆了,難受。
牛客網NowCoder 2018年全國多校算法寒假訓練營練習比賽(第五場)A.逆序數 B.Big Water Problem(線段樹-區間查詢求和和單點更新) F.The Biggest Water Problem H.Tree Recovery(線段樹-區間查詢求和和區間更新)