單點更新 區間查詢php
敵兵佈陣 html
坑點:cin cout 一直超時 改爲 scanf 和printf 就過了算法
/*輸入 t樣例 N(N<=50000) 第i個正整數ai表明第i個工兵營地裏開始時有ai我的(1<=ai<=50)。 接下來每行有一條命令,命令有4種形式: (1) Add i j,i和j爲正整數,表示第i個營地增長j我的(j不超過30) (2)Sub i j ,i和j爲正整數,表示第i個營地減小j我的(j不超過30); (3)Query i j ,i和j爲正整數,i<=j,表示詢問第i到第j個營地的總人數; (4)End 表示結束,這條命令在每組數據最後出現; 1 10 1 2 3 4 5 6 7 8 9 10 Query 1 3 Add 3 6 Query 2 7 Sub 10 2 Add 6 3 Query 3 10 End 輸出 Case 1: 6 33 59 */ #include <string.h> #include <stdio.h> using namespace std; int n,t[50005]; int lowbit(int x) { return x&(-x); } void update(int x,int val)//單點更新 { while(x<=n){ t[x]+=val; x+=lowbit(x);//由葉子節點向上更新樹狀數組C,從左往右更新 } } int ask(int x)//求區間[1,i]內全部元素的和 即求前綴和 { int ans=0; while(x>0){ ans+=t[x];//從右往左累加求和 x-=lowbit(x); } return ans; } int main() { int tt,cnt=0,b,c,i,a; char s[10]; scanf("%d",&tt); while(tt--) { scanf("%d",&n); memset(t,0,sizeof(t)); for(i=1;i<=n;i++) { scanf("%d",&a); update(i,a); } printf("Case %d:\n",++cnt); while(scanf("%s",s)) { if(s[0]=='E') break; scanf("%d%d",&c,&b); if(s[0]=='S') update(c,-b); if(s[0]=='A') update(c,b); if(s[0]=='Q') { printf("%d\n",ask(b)-ask(c-1)); } } } return 0; }
這個題把數據離散化了 ,利用樹狀數組求數據的逆序對 ,即超快排的交換次數。ide
/* 在此問題中,您必須分析特定的排序算法。該算法經過交換兩個相鄰的序列元素, 直到該序列以升序排序,來處理n個不一樣整數的序列。對於輸入序列 9 1 0 5 4, Ultra-QuickSort產生輸出 0 1 4 5 9。 您的任務是肯定Ultra-QuickSort須要執行多少次交換操做才能對給定的輸入序列進行排序。 輸入項 輸入包含幾個測試用例。每一個測試用例均以包含單個整數n <500,000(輸入序列的長度)的一行開頭。 接下來的n行中的每行都包含一個整數,即0≤a [i]≤999,999,999,即第i個輸入序列元素。輸入由長度爲n = 0的序列終止。 不得處理此序列。 輸出量 對於每一個輸入序列,程序將打印一行包含整數op的單行,op是對給定輸入序列進行排序所需的最小交換操做數。 Input 5 9 1 0 5 4 3 1 2 3 0 Output 6 0 */ #include <string.h> #include <stdio.h> #include <algorithm> #define maxn 500010 using namespace std; long long int n, a[maxn], b[maxn],t[maxn]; int lowbit(int x) { return x&(-x); } void update(int x,int val)//單點更新w { while(x<=n){ t[x]+=val; x+=lowbit(x);//由葉子節點向上更新樹狀數組C,從左往右更新 } } long long int ask(int x)//求區間[1,i]內全部元素的和 即求前綴和 { long long int ans=0; while(x>0){ ans+=t[x];//從右往左累加求和 x-=lowbit(x); } return ans; } int main() { long long int ans=0; //這裏如下標1爲序列的起點,通常狀況下從0開始也能夠 while(scanf("%lld",&n)) { if(!n) break; for(int i = 1;i <= n;i++) { scanf("%lld", &a[i]); b[i] = a[i];//b是一個臨時數組,用來獲得離散化的映射關係 } //下面使用了STL中的sort(排序),unique(去重),lower_bound(查找)函數 sort(b + 1, b + n + 1);//排序 int size = unique(b + 1, b + 1 + n) - b - 1;//去重,並得到去重後的長度size for(int i = 1;i <= n;i++) { a[i] = lower_bound(b + 1, b + 1 + size, a[i]) - b;//經過二分查找,快速地把元素和映射對應起來 update(a[i],1); ans +=(i-ask(a[i])); } printf("%lld\n",ans); ans=0; memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); memset(t,0,sizeof(t)); } return 0; }