C1. Sheikh (Easy version)

Posted on 2022-10-26 22:22  Capterlliar  阅读(47)  评论(0编辑  收藏  举报

题意:定义[l,r]的价值为:区间[l,r]里面数的算术和减去它们的异或和。求出整个序列内价值最大的最短区间。

解:奇怪的运算,试图找它的性质。已知异或是不进位的加法,那异或得到的结果一定比进位的加法,也就是正常的加法小。这意味着添加一个数,它的价值一定会变大,那么最大价值一定等于[1,n]的价值。现在要找出一个最短的区间,其价值也等于[1,n]的价值。由于价值具有单调性,所以线性地扫一遍就可以了。

代码:

#include <bits/stdc++.h>
using namespace std;
#define maxx 100005
#define maxn 25
#define maxm 205
#define ll long long
#define inf 1000000009
#define mod 998244353
ll a[maxx]={0},sum1[maxx]={0},sum2[maxx]={0};
ll cal(int l,int r){
    return (sum1[r]-sum1[l-1])-(sum2[r]^sum2[l-1]);
}
signed main() {
    int T;
    scanf("%d",&T);
    while(T--){
        int n,q;
        scanf("%d%d",&n,&q);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        int l0,r0;
        scanf("%d%d",&l0,&r0);
        for(int i=1;i<=n;i++){
            sum1[i]=sum1[i-1]+a[i];
        }
        for(int i=1;i<=n;i++){
            sum2[i]=sum2[i-1]^a[i];
        }
        int r=1;
        ll res=cal(1,n);
        int ans=inf,ansl=1,ansr=n;
        for(int l=1;l<=n;l++){
            if(r<l) r=l;
            while(cal(l,r)<res&&r<n) r++;
            if(cal(l,r)==res&&r-l+1<ans){
                ans=r-l+1;
                ansl=l,ansr=r;
            }
        }
        printf("%d %d\n",ansl,ansr);
    }
    return 0;
}
View Code