日常刷水。。。
单调栈,按位搞。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 100050 #define mod 1000000061 using namespace std; long long t,n,a[maxn],l[maxn],r[maxn],cnt[maxn][31][2],s[maxn],top=0,sum[maxn]; long long read() { char ch;long long data=0; while (ch<'0' || ch>'9') ch=getchar(); while (ch>='0' && ch<='9') { data=data*10+ch-'0'; ch=getchar(); } return data; } void work(int x) { for (int i=0;i<=30;i++) cnt[0][i][0]=1; n=read(); for (long long i=1;i<=n;i++) {a[i]=read();sum[i]=sum[i-1]^a[i];} for (long long i=1;i<=n;i++) for (long long j=30;j>=0;j--) { cnt[i][j][0]=cnt[i-1][j][0];cnt[i][j][1]=cnt[i-1][j][1]; cnt[i][j][((sum[i]&(1<<j))>0)]++; } top=0; for (long long i=1;i<=n;i++) { while (top && a[s[top]]<=a[i]) top--; l[i]=s[top]+1;s[++top]=i; } top=0; for (long long i=n;i>=1;i--) { while (top && a[s[top]]<a[i]) top--; if (top) r[i]=s[top]-1;else r[i]=n; s[++top]=i; } long long ans=0; for (long long i=1;i<=n;i++) for (long long j=0;j<=30;j++) { long long bit; if (i==1) bit=cnt[r[i]][j][1]-cnt[i-1][j][1]; else if (l[i]==1) bit=cnt[i-1][j][0]*(cnt[r[i]][j][1]-cnt[i-1][j][1])%mod+cnt[i-1][j][1]*(cnt[r[i]][j][0]-cnt[i-1][j][0])%mod; else bit=(cnt[i-1][j][0]-cnt[l[i]-2][j][0])*(cnt[r[i]][j][1]-cnt[i-1][j][1])%mod+(cnt[i-1][j][1]-cnt[l[i]-2][j][1])*(cnt[r[i]][j][0]-cnt[i-1][j][0])%mod; bit%=mod; ans+=bit*((1<<j)%mod)%mod*a[i]%mod;ans%=mod; } printf("%lld\n",ans); } int main() { t=read(); for (long long i=1;i<=t;i++) work(i); return 0; }