「CodePlus 2017 11 月赛」可做题

  这种题先二进制拆位,显然改的位置只有每一段确定的数的开头和结尾,只需要对于每一个可决策位置都尝试一下填1和0,然后取min即可。

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=500010;
const ll inf=1e15;
struct poi{int pos, w;}a[maxn];
int n, m, tot, xor0, xor1;
ll sum0, sum1, ans, ans0;
inline void read(int &k)
{
    int f=1; k=0; char c=getchar();
    while(c<'0' || c>'9') c=='-' && (f=-1), c=getchar();
    while(c<='9' && c>='0') k=k*10+c-'0', c=getchar();
    k*=f;
}
inline bool cmp(poi a, poi b){return a.pos<b.pos;}
int main()
{
    read(n); read(m);
    for(int i=1;i<=m;i++) read(a[i].pos), read(a[i].w);
    sort(a+1, a+1+m, cmp); m++;
    for(int j=0;j<30;j++)
    {
        tot=xor0=sum0=xor1=ans0=0;
        sum1=(a[1].pos==1)?inf:0;
        for(int i=1;i<=m;i++)
        {
            if(a[i].pos-1!=a[i-1].pos)
            {
                ans0=min(ans0+sum0, ans0+sum1+1);
                xor0=sum0=sum1=0; xor1=1;
            }
            xor0^=(a[i].w&(1<<j))!=0; xor1^=(a[i].w&(1<<j))!=0;
            sum0+=xor0; sum1+=xor1;
        }
        ans+=ans0<<j;
    }
    printf("%lld
", ans);
}
View Code
原文地址:https://www.cnblogs.com/Sakits/p/8092402.html