码迷,mamicode.com
首页 > 其他好文 > 详细

习题:changing array (贪心)

时间:2020-01-31 18:38:38      阅读:57      评论:0      收藏:0      [点我收藏+]

标签:using   pre   cin   line   ble   前缀和   表示   class   i++   

题目

传送门

思路

正难则反,全集是很好求的,即为\(\frac{n*(n+1)}{2}\),想要异或不为0的尽可能的多,即异或为0的尽可能的少

对于所有的区间\(l,r\),可以用前缀和\(s\)来表示,\(s_r ~xor~s_{l-1}\)

之后我们考虑\(xor\)的性质,只有当两个数相同时,异或值才为0

我们设\(t_k\)表示有多少个前缀和为\(k\)

对于第\(i\)个数,我们贪心的考虑就好了,看是不异或少,还是异或之后少就行了

贪心的正确性显然

\(t_0\)初始值应为1,因为你还要算他本身的贡献

代码

#include<iostream>
#include<map>
using namespace std;
int n,k;
int a[200005];
map<int,int> t;
int _last;
long long ans;
int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>k;
    k=(1<<k)-1;
    ans=1ll*(n+1)*n/2;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    t[0]=1;
    for(int i=1;i<=n;i++)

    {
        int u=a[i]^_last,v=a[i]^k^_last;
        if(t[u]<t[v])
        {
            ans-=t[u];
            t[u]++;
            _last=u;
        }
        else
        {
            ans-=t[v];
            t[v]++;
            _last=v;
        }
    }
    cout<<ans;
    return 0;
}

习题:changing array (贪心)

标签:using   pre   cin   line   ble   前缀和   表示   class   i++   

原文地址:https://www.cnblogs.com/loney-s/p/12246006.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!