Gym - 101755G Underpalindromity (树状数组)
Let us call?underpalindromity?of array?b?of length?k?the minimal number of times one need to increment some elements?bj?by 1 so that the array?b?would become a palindrome, that is,?b1?=?bk,?b2?=?bk?-?1, and so on.
The array of length?n, consisting of integers, is given. Consider all its subarrays of length?k, and for each of these subarrays its?underpalindromity?pi. It's needed to calculate sum of all?pi?(1?≤?i?≤?n?-?k?+?1).
Input
The first line contains two integers?n?and?k?(1?≤?k?≤?n?≤?200000)?— the length of the array and the length of subarrays.
The second line contains?n?integers?ai?(?-?108?≤?ai?≤?108)?— the elements of the array.
Output
Output a single integer?— sum of?underpalindromities?of all subarrays of length?k.
Examples
Input 3 23 1 2 Output 3 Input 5 3
2 3 3 1 4 Output 4
題意:
給定一個數組,要把每一個長度為K的子串臨時變為回文的(每個子串即使有重疊,也互不影響),需要加上的值的總和。
思路:
按數字從小到大排序。
樹狀數組我一共開了四個,分別用以維護區間內:奇數位置的數字和,奇數位置的數字個數,偶數位置的數字和,偶數位置的數字個數。
對于某一個數,和它相關的數一定是奇偶一致的。而且與它有關的數,只要算上一次就行了。和它有關的數的區間,可以O(1)算出.
設有一個數a,與其有關的有一個數b,那么這對數就有一個貢獻是|a-b|
所以我們便可以將數字從小到大排序,于是就可以很好處理這個絕對值了。
然后對于某一個數,它與比它小的數字的貢獻,就是和它有關的區間的數字數量*這個數-和它有關的區間的數字之和。與比它大的貢獻,留給比它大的數來算。
接下來的問題就是算出和這個數的區間的。
如果左邊或者右邊的長度大于k,那么結果是顯而易見的。如果小于,對于左邊,那就只要考慮以1開始的那個子串有關就行了。
右邊同理。 1 #include<iostream> 2 #include<algorithm> 3 #include<vector> 4 #include<stack> 5 #include<queue> 6 #include<map> 7 #include<set> 8 #include<cstdio> 9 #include<cstring> 10 #include<cmath> 11 #include<ctime> 12 #define fuck(x) cout<<#x<<" = "<<x<<endl; 13 #define ls (t<<1) 14 #define rs ((t<<1)+1) 15 using namespace std; 16 typedef long long ll; 17 typedef unsigned long long ull; 18 const int maxn = 200086; 19 const int inf = 2.1e9; 20 const ll Inf = 999999999999999999; 21 const int mod = 1000000007; 22 const double eps = 1e-6; 23 const double pi = acos(-1); 24 ll num1[maxn],val1[maxn],num2[maxn],val2[maxn]; 25 int n,k; 26 struct node{ 27 ll num; 28 int id; 29 }a[maxn]; 30 int lowbit(int x){ 31 return x&(-x); 32 } 33 void update(ll *bit,int p,ll num){ 34 while(p<=n){ 35 bit[p]+=num; 36 p+=lowbit(p); 37 } 38 } 39 40 ll query(ll *bit,int p){ 41 ll ans=0; 42 while(p>0){ 43 ans+=bit[p]; 44 p-=lowbit(p); 45 } 46 return ans; 47 } 48 49 bool cmp(node a,node b){ 50 return a.num<b.num; 51 } 52 53 int main() 54 { 55 scanf("%d%d",&n,&k); 56 for(int i=1;i<=n;i++){ 57 scanf("%lld",&a[i].num); 58 a[i].id=i; 59 } 60 sort(a+1,a+1+n,cmp); 61 ll ans=0; 62 for(int i=1;i<=n;i++){ 63 int l,r; 64 if(a[i].id>=k)l=a[i].id-k+1; 65 else{l=k-a[i].id+1;} 66 if(a[i].id+k-1<=n){r=a[i].id+k-1;} 67 else{r=2*n-a[i].id-k+1; } 68 if((a[i].id+k-1 )&1){ 69 ans-=query(val1,r)-query(val1,l-1); 70 ans+=a[i].num*(query(num1,r)-query(num1,l-1)); 71 } 72 else{ 73 ans-=query(val2,r)-query(val2,l-1); 74 ans+=a[i].num*(query(num2,r)-query(num2,l-1)); 75 } 76 if(a[i].id&1){ 77 update(val1,a[i].id,a[i].num); 78 update(num1,a[i].id,1); 79 } 80 else{ 81 update(val2,a[i].id,a[i].num); 82 update(num2,a[i].id,1); 83 } 84 } 85 printf("%lld\n",ans); 86 87 return 0; 88 } View Code
?
轉載于:https://www.cnblogs.com/ZGQblogs/p/10553792.html
總結
以上是生活随笔為你收集整理的Gym - 101755G Underpalindromity (树状数组)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [51nod1201]整数划分
- 下一篇: [优先队列] 洛谷 P1631 序列合并