Codeforces Round #814 (Div. 1) A1. Burenka and Traditions (easy version)

 

 

 

这是这个问题的简单版本。简单版本和硬版本之间的区别只是𝑎𝑖和𝑛上的约束。只有两个版本的问题都解决了,你才能进行hack。

布伦卡是布里亚特的王储公主,很快她将成为这个国家的𝑛-th女王。布里亚特有一个古老的传统——在加冕典礼之前,统治者必须向居民展示他们的力量。为了确定𝑛-th尺子的强度,这个国家的居民给他们一个𝑎的数组,正好是𝑛的数字,之后尺子必须在最短的时间内把数组中的所有元素都变成零。标尺可以执行以下两步操作任意次数:

选择两个指标𝑙和𝑟,使1≤𝑙≤𝑟≤𝑛和一个非负整数𝑥,则
对于所有𝑙≤𝑖≤𝑟分配𝑎𝑖:=𝑎𝑖⊕𝑥,其中⊕表示按位异或操作。执行这个操作需要⌈𝑟−𝑙+12⌉秒,其中⌈𝑦⌉表示𝑦四舍五入到最接近的整数。
帮助布伦卡计算她需要多少时间。

输入
第一行包含单个整数𝑡(1≤𝑡≤500)—测试用例的数量。下面是测试用例的描述。

每个测试用例的第一行包含单个整数𝑛(1≤𝑛≤5000)—数组的大小。

每个测试用例的第二行包含𝑛整数𝑎1,𝑎2,…,𝑎𝑛(0≤𝑎𝑖≤5000)——数组的元素。

保证所有测试中𝑛的总和不超过5000。

输出
对于每个测试用例,输出一个数字—Burenka需要的最小时间。

例子
inputCopy
7
4
5 5 5 5
3.
1 3 2
2
0 0
3.
2 5 7
6
1 2 3 3 3 2 1
10
27 27 34 32 2 31 23 56 52 4
5
1822 1799 57 23
outputCopy
2
2
0
2
4
7
4
请注意
在第一个测试用例中,Burenka可以选择段𝑙=1、𝑟=4和𝑥=5。它会在2秒内用0填满数组。

在第二个测试用例中,Burenka首先选择段𝑙=1、𝑟=2和𝑥=1,之后选择𝑎=[0,2,2],然后选择段𝑙=2、𝑟=3和𝑥=2,用0填充数组。布伦卡总共需要2秒。

题意:可以选择一段区间然后进行按位异或的操作,然后成本是【r-l+1/2】 ,让数组中所以元素都变为0。

思路:最小化成本,长段区间其实可以分成1 2长度的区间,然后其操作成本一样,所以只需要往后扩展,然后记录前边是否有相同的前缀异或值,如果有的话,再对当前异或值来进行比较,状态转移即可。

代码:
 

#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <stdio.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<tuple>
#include<numeric>
#include<stack>
using namespace::std;
typedef long long  ll;
int n,t;
inline __int128 read(){
    __int128 x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if(ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}
inline void print(__int128 x){
    if(x < 0){
        putchar('-');
        x = -x;
    }
    if(x > 9)
        print(x / 10);
    putchar(x % 10 + '0');
}

int a[5005];
ll s[5005];
ll dp[5005];
void solv(){
    memset(dp, 0, sizeof dp);
    map<ll,ll>q;
    s[0]=0;
    q[0]=0;
    cin>>n;
    for (int i =1; i<=n; i++) {
        cin>>a[i];
        s[i]=s[i-1]^a[i];
    }
    for (int i =1; i<=n; i++) {
        if (a[i]==0) {
            dp[i]=dp[i-1];
            q[s[i]]=i;
            continue;
        }
        
        if (q.count(s[i])) {
            dp[i]=min(dp[i-1]+1, dp[q[s[i]]]+i-q[s[i]]-1);
        }
        else{
            dp[i]=dp[i-1]+1;
        }
        q[s[i]]=i;
    }
    
//    for (int i =1; i<=n; i++) {
//        printf("%lld ",s[i]);
//    }printf("\n");
//
//    for (int i =1; i<=n; i++) {
//        printf("%lld ",dp[i]);
//    }
//    printf("\n");
    printf("%lld\n",dp[n]);
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(); cout.tie();
    cin>>t;
    while (t--) {
        solv();
    }
    return 0;
}
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值