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 = bkb2 = 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 2
3 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

 

posted @ 2019-03-18 18:00  断腿三郎  阅读(269)  评论(0编辑  收藏  举报