CodeForces1323 D.プレゼント(二点)

質問の意味:

長さNの配列の
計算要件((1)+( 2)) XOR((1)+( 3)) XOR ...((1)+ (N)) XOR ((2)+( 3)) XOR ...((2)+ (N)) XOR((3)+( 4))...((N-1)+(nは))。
それは、すべてです「との追加注文」とXORを。
データ範囲:N <= 4e5,1 <= A (I)<= 1E7

アイデア:

元のタイトル(参照することはできません):AtCoder3943二つの配列

基本的には同じ考え。

参照XORは、ビットの貢献に考えるのは簡単です
が、ほかは面倒だった、さらにはキャリーを生成すること、また、キャリーをどのように扱うかは非常に良い考えではありません。
私たちは、xビットの位置xよりも明らかに高い、その後、Xの貢献の現在位置を計算すると仮定しますと、1は、影響を与えることはありませんだけで、バイナリビット×1を考慮することです。
= T 2セットxは、アレイ2Tは下位Xビットが得られる値を法。
(I)+(Jするために ) x番目のビットが1であると、それは次の2つの条件のいずれか取る:
T <=(I)+(J ) <2Tを、(x番目のビットのキャリーが発生しませんこの条件は、Xビットが1であり、Xは任意)は、以下のビットで
3T <= A(I)+ A(J)<4T、(結果のXビットが発生し、条件ビットX及びX + 1ビットであります図1に示すように、任意の位置x以下)
(I)を挙げることができ、それぞれ、2つの2セクションは2つのエンドポイントは、これらの二つの条件を満たしている分離、間隔の長さは、数1つのxビットの数であります

注いくつかのポイントがある:
1区間の長さの和は、疾患の数の和を算出しているため、要求の対象が順序対で、総数は2で除算され
、各Aの2(i)は、低減する必要が自分の状況(:、最初のiが決定される間隔で、第二、自分自身を追加し、最初のビットが1×であるか否かを判断する決意法)と一致します。

数が奇数の場合は最後に、現在位置の寄与の合計が答える場合。

PS:
手書き半分内のコードは、そのコードサイズが非常に大きくなります。
小さな変化量がコードをLOWER_BOUND場合は、コードがたくさん短くなります。

コード:

#include<bits/stdc++.h>
using namespace std;
const int maxm=4e5+5;
int a[maxm];
int b[maxm];
int n;
int ask(int left,int right,int idx){//计算b数组中left<=x<right的x的数量
    int st=0,ed=0;
    int l=1,r=n;
    while(l<=r){//st尽量向左扩展
        int mid=(l+r)/2;
        if(b[mid]>=left){
            st=mid;
            r=mid-1;
        }else{
            l=mid+1;
        }
    }
    l=1,r=n;
    while(l<=r){//ed尽量向右扩展
        int mid=(l+r)/2;
        if(b[mid]<right){
            ed=mid;
            l=mid+1;
        }else{
            r=mid-1;
        }
    }
    if(!st||!ed)return 0;//如果不能同时满足x>=left且x<right,则无解
    int ans=ed-st+1;
    if(st<=idx&&ed>=idx)ans--;//自己不能和自己匹配,如果自己在区间内就减1
    return ans;
}
signed main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    int ans=0;
    for(int i=0;i<25;i++){
        int t=(1<<i);
        for(int j=1;j<=n;j++){
            b[j]=a[j]%(t*2);
        }
        sort(b+1,b+1+n);
        int cnt=0;
        for(int j=1;j<=n;j++){
            cnt+=ask(t-b[j],t*2-b[j],j);
            cnt+=ask(t*3-b[j],t*4-b[j],j);
        }
        cnt/=2;//因为题目要求的数对是有序对,所以要除以2
        if(cnt&1)ans+=(1<<i);
    }
    printf("%d\n",ans);
    return 0;
}

公開された430元の記事 ウォン称賛36 ビュー20000 +

おすすめ

転載: blog.csdn.net/weixin_44178736/article/details/104726793