[Wannafly Challenge 1] B Xorto [Mind + Divide]

Time limit: C/C++ 2 seconds, 4 seconds for other languages
Space limitations: C/C++ 32768K, other languages 65536K
64bit IO Format: %lld
Title Description
Given an array of integers of length n, ask how many pairs of non-empty intervals do not overlap each other so that the XOR of the numbers in the two intervals is zero.
Enter a description:
The first line, an number n, represents the length of the array.
The second row of n integers represents the array;
1<=n<=1000,0<=array element<100000.
Output description:
One integer per line represents the answer.
Example 1
input

3
0 0 0
output

5
Explain

([1,1],[2,2]),([1,1],[3,3]),([1,1],[2,3]),([1,2],[3,3]),([2,2],[3,3])

Analysis:
1 When you look at the problem of intervals, you can first think about whether you can use the expression of prefix XOR to get the XOR of any interval from o(1). To test with data, you can do it really, make a prefix XOR table, and then for any interval [le,ri] the XOR is pre[ri]^pre[le-1].
2 Now that the problem is converted to, [L1,R1] ^ [L2,R2] =0 (also non-overlapping intervals), according to the XOR property, we know that the XOR value of [L1,R1] must be equal to the XOR value of [L2,R2].
3 Then we can iterate through all the intervals with n^2 and save all the intervals with the same XOR value.Then iterate through all the intervals, and for each interval, see how many nonoverlapping intervals have the same XOR value as the current interval.[Optimize here, see the code in more detail]

#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int MAXN = 1e3+11;
const int MAXM = 1000000+11;// Notice here that it is not the size of the element value, but the arbitrary XOR maximum within the range of the element values.
//The maximum is the new value that changes all digits to 1 in the binary of 1e5.
typedef pair <int,int>pii;
const int inf = 0x3f3f3f3f;

vector<pii>ve[MAXM];
int a[MAXN],ans[MAXN];int n;
int Getval(int le,int ri){ return ans[ri]^ans[le-1]; }

int erfen(int c,int val){  //For sequence ve[c], find out how many numbers are greater than val
    int le=0,ri=ve[c].size()-1;
    int ans=-1;
    while(le<=ri){
        int mid=(le+ri)/2;
      //  printf("mid %d ve[c][mid].first %d\n",mid,ve[c][mid].first);
        if(ve[c][mid].first>val) {
            ans=mid ; ri=mid-1;
        }else le=mid+1;
    }
    if(ans==-1) return 0;
    return ve[c].size()-ans;
}

int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)  scanf("%d",&a[i]);
        for(int i=1;i<=n;i++) ans[i]=a[i]^ans[i-1];

        for(int i=1;i<=n;i++){
            for(int j=i;j<=n;j++){
                int c=Getval(i,j);
                ve[c].push_back(pii{i,j});
            }
        }
        /*
        LL an=0;  // Write this at the beginning, the result timed out 
        for(int i=1;i<=n;i++){
            for(int j=i;j<=n;j++) {
                int c=Getval(i,j);
                    for(int k=0;k<ve[c].size();k++){
                        pii p=ve[c][k];
                        if(p.first>j) { // Intervals do not overlap, for [L1,R1] and [L2,R2] do not overlap As long as L2 > R1 OR R2 < L1, but we just pick one direction, otherwise we will repeat 
                               // printf("i=%d j=%d  pi=%d pj=%d\n ",i,j,p.first,p.second);
                            an++;
                        }
                    }
            }
        }
        */
        LL an=0; // Then I wrote this, adding a two point
        for(int i=1;i<=n;i++){
            for(int j=i;j<=n;j++) {
                int c=Getval(i,j);
                an+=erfen(c,j);  // Because I traverse the interval in increasing order by the left endpoint, the sequence is ordered.
            }
        }
        printf("%lld\n",an);
return 0;
}

Posted on Fri, 03 Jul 2020 10:36:47 -0400 by goa103