Codeforces Ronda # 626 D. XOR presente determina el doble puntero o + bit binario

Codeforces Ronda # 626 D. XOR presente determina el doble puntero o + bit binario

El significado de los problemas

Un número n, y pedirles de dos en dos exclusiva o resultado de n (4E5) rango (1E7)

pensamiento

problema XOR se determina generalmente por bit, entonces la forma de determinar el valor de los k bits de ella. En primer lugar, el valor de la única k bits y [1, k] bits de una relación, que es sólo en esta relación tendría un número y llevar algo con un [i]. Entonces, ¿cómo lidiar con el problema y hacer. En primer lugar, consideramos solamente poco [1..k], y luego se registran como suma, si la suma del valor de k bits es entonces la suma de \ (2 ^ k + x \ ) porque sólo consideran [1..k ] Por lo tanto, el valor máximo de un bit es \ (2 ^ {k + 1 } -1 \) un valor máximo de la suma es \ (2 ^ {k + 2 } -2 \) así que podemos conseguir como \ ([^ 2 k, 2 ^ {k + 1 } -1] \) , y [2 ^ {k + 1} + 2 ^ {k} -1,2 ^ {k + 2} -2] Si la suma cae dos tramos en, a continuación, su bit k-ésimo es 1. Queremos contar y se encuentra dentro de los dos rangos, está claro que la primera de una serie mod pocos podemos \ (2 ^ {k + 1 } \) ordenados usando un medio rango buscando. Tal complejidad es 0 (nlognlogc) igual que monótono, puede utilizar el doble puntero por tanto, menos de un registro se convierte en O (nlogc)

bipartito

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define F first
#define S second
#define mkp make_pair
#define pii pair<int,int>
typedef long long ll;
#define int ll
const int inf=0x3f3f3f3f;
const int maxn=4e5+5;
const int mod= 998244353;
int b[maxn],a[maxn];
int n;
int solve(int x,int y,int z){
 
        if(y<x)return 0;
        int l=lower_bound(b+1,b+1+n,x)-b;
        int r=upper_bound(b+1,b+1+n,y)-b;
            //cout<<x<<" fuck"<<y<<" "<<(n-l+1)-(n-r+1)<<endl;
        int flag=0;
        if(z>=x&&z<=y)flag=1;
        return (n-l+1)-(n-r+1)-flag;
}
int32_t main(){
    scanf("%lld",&n);
    int up=0;
    for(int i=1;i<=n;i++)scanf("%lld",&a[i]),up=max(up,a[i]);
    int ans=0;
    
    for(int k=1;k<=2e7;k<<=1){
        for(int j=1;j<=n;j++)b[j]=a[j]%(k*2ll);
        sort(b+1,b+1+n);
        int sum=0;
        for(int j=1;j<=n;j++){
        //  cout<<solve((1<<(k-1))-b[j],(1<<k)-b[j]-1)<<" "<<solve((1<<(k-1))+(1<<(k))-b[j],(1<<(k+1))-2-b[j]);
            //cout<<endl;
        //  cout<<j<<" "<<((1<<(k-1))-b[j])<<" "<<((1<<k)-b[j]-1)<<" "<<solve((1<<(k-1))-b[j],(1<<k)-b[j]-1)<<endl;
            //cout<<j<<" "<<((1<<(k-1))+(1<<(k))-b[j])<<" "<<((1<<(k+1))-2-b[j])<<" "<<solve((1<<(k-1))+(1<<(k))-b[j],(1<<(k+1))-2-b[j])<<endl;
            sum+=solve(k-b[j],2ll*k-b[j]-1,b[j]);
            sum+=solve(2ll*k+k-b[j],k*4ll-2-b[j],b[j]);
        }
        sum/=2;
    //  cout<<sum<<endl;
        if(sum&1)ans^=(k);
    }
    printf("%lld\n",ans);
    return 0;
}

doble puntero

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define F first
#define S second
#define mkp make_pair
#define pii pair<int,int>
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=4e5+5;
const int mod= 998244353;
int b[maxn],a[maxn];
int n;
 
int main(){
    scanf("%d",&n);
    int up=0;
    for(int i=1;i<=n;i++)scanf("%d",&a[i]),up=max(up,a[i]);
    int ans=0;
    for(int k=1;k<=2e7;k<<=1){
        for(int j=1;j<=n;j++)b[j]=a[j]%(k*2ll);
        sort(b+1,b+1+n);
        long long  sum=0;
        int p1=1,p2=1,p3=1;
        for(int j=n;j>=1;j--){
            while(p1<=n&&b[p1]+b[j]<k)p1++;
            while(p2<=n&&b[p2]+b[j]<k+k)p2++;
            while(p3<=n&&b[p3]+b[j]<k+k+k)p3++;
            sum+=max(0,min(j,p2)-p1);
            sum+=max(0,j-p3);
        }
        if(sum&1)ans^=(k);
    }
    printf("%d\n",ans);
    return 0;
}

Supongo que te gusta

Origin www.cnblogs.com/ttttttttrx/p/12444098.html
Recomendado
Clasificación