题意:定义[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; }