標籤:ota 假設 problem 好的 space its tao 暴力 int
連結:http://acm.hdu.edu.cn/showproblem.php?pid=6406
思路:
暴力,預先處理三個首碼和:【1,n】桃子會被摘掉,1到當前點的最大值,1到當前點被摘掉的桃子的數量,然後我們枚舉修改p點造成的所有影響,:
1,假如新輸入的點比原先的點的值更大,那麼我們對修改後p這個點的值和【1,p-1】的最大值關係進行分析,也就是分析前半段的影響:(1)如果p點大於1-p-1的最大值的時候我們直接利用首碼和O(1)得到【1,p-1】有多少個桃子被摘掉,然後加上當前這個。(2)如果p點小於等於【1,p-1】的最大值時,對前半段和後半段都不會造成影響,直接輸出預先處理的到的【1,n】的值就好了;然後我們分析後半段的影響:(1)如果p點大於【1,p-1】的最大值,那麼後半段中只有被摘掉的桃子會受到影響,我們直接二分找到【p+1,n】中被摘掉的桃子的值大於被修改後的值c的下標,減一下,就得出了,後半段會被摘掉的桃子中有幾個在p點被修改後依舊需要摘掉,將後半段的值與前半段的值加起來就好了。(2)如果p點小於等於【1,p-1】的最大值,那麼後半段不造成影響,
2.假如新輸入的點小於等於原先的點值,依舊對修改後p這個點的值和【1,p-1】的最大值進行分析:先分析前半段的影響:(1)如果p點大於1-p-1的最大值的時候我們直接利用首碼和O(1)得到【1,p-1】有多少個桃子被摘掉,然後加上當前這個。(2)如果p點小於等於【1,p-1】的最大值,那麼這個點依舊對前半段不造成影響,前半段的值等於【1,p-1】中被摘掉的桃子的數量,
接下來就是最難得後半段的討論:
之前處理這裡思路被卡了很久:(1)如果p點大於1-p-1的最大值
因為當前點變小了,對後面點造成的影響就是會摘掉一些原先不會被摘的桃子,那麼怎麼確定這些桃子的具體是那些呢? 實際上我們可以推出,這些多摘的桃子都是在1到當前座標中只小於p的數,因為這些數是當p變小了才多出來的,那麼他們在1到當前點肯定是只小於p點,那麼我們把它加到前一維為p的vecvector數組裡,至於怎麼找到這些值,我們只要多維護一個第二大值就可以了,這些第二大值就是有可能會多摘的桃子。當p點為原先會被摘的桃子時我們對存在v[p]裡的值進行二分找到比p值修改後大的那些值,也就是後半段新增的值,再加上原先就要摘得值。
(2) 如果小於等於的話,依舊不造成影響,直接去首碼和就好了
3,假設輸入的點和原來的點值一樣,直接首碼和取
這樣一共是五種主要情況: 兩種用二分O(logn),另外三種直接首碼和O(1),稍微計算便可知不會逾時。最後跑了405ms,題目給了2000mS,算跑的很快的了, 就是實現有點複雜,應該還有更好的解法,不過比賽的時候沒想那麼多,直接暴力莽過去了,還好過了要不改代碼要改到吐。。QAQ
實現代碼:
#include<bits/stdc++.h>using namespace std;const int M = 1e5+10;struct node{ int id,val;};vector<int>v[M];int a[M],ans[M],maxx[M],b[M],arr[M];int main(){ int t,n,q,p,c; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&q); for(int i = 1;i <= n;i ++){ scanf("%d",&a[i]); } node mx,mx1; mx.val = 0; mx1.val = 0,mx.id = 0,mx1.id = 0; int cnt = 0,num = 0; maxx[0] = 0; for(int i = 1;i <= n;i ++){ if(mx.val < a[i]){ mx1.val = mx.val; mx1.id = mx.id; mx.val = a[i]; mx.id = i; b[cnt++] = a[i]; num++; } else if(mx1.val < a[i]){ mx1.val = a[i]; mx1.id = i; v[mx.id].push_back(a[i]); } maxx[i] = mx.val; ans[i] = num; } while(q--){ scanf("%d%d",&p,&c); int sum = 0; if(c > a[p]){ if(c > maxx[p-1]){ sum ++; sum += ans[p-1]; int kk = upper_bound(b,b+cnt,c) - b; if(kk != cnt) sum += cnt-kk; } else sum = ans[n]; } else if(c == a[p]) sum = ans[n]; else{ if(c > maxx[p-1]) sum++,sum += ans[p-1]; else sum += ans[p-1]; if(a[p] == maxx[p]){ int kk = upper_bound(v[p].begin(),v[p].end(),c)-v[p].begin(); sum += v[p].size() - kk; int kk1 = upper_bound(b,b+cnt,a[p]) - b; if(kk1 != cnt) sum += cnt-kk1; } else sum = ans[n]; } printf("%d\n",sum); } for(int i = 0;i <= n;i ++){ maxx[i] = 0; ans[i] = 0; v[i].clear(); } for(int i = 0;i <= cnt;i ++) b[i] = 0; } return 0;}
hdu 6406 Taotao Picks Apples (2018 Multi-University Training Contest 8 1010)(二分,首碼和)