mayoko’s diary

プロコンとかいろいろ。

SRM649div2hard:XorSequenceEasy

問題:http://community.topcoder.com/stat?c=problem_statement&pm=13657&rd=16313

解法:注目すべき性質は2つ。
①整数の大小関係はbit数の大きいものを優先に決定される
②整数aとbのk番目のbit数が同じであるとすると、k番目のbitが1の整数cを使ってa = a^c, b = b^cとしても大小関係は変化しない
解法のアイデアとしては、「k番目のbitを0にするか1にするか?」ということを考える。これを考える時、考慮しなければならないことは、A[i], A[j](i < j)のk番目のbitが、A[i]とA[j]で異なる最大のbit数であるような(i, j)の組み合わせのみである。なぜかというと、まずkより大きいbit数で大小関係が決定されるものについては性質①より、k番目のbit数は何も影響しない。またkより小さいbit数で大小関係が決定されるものは、k番目のbit数は同じことになるので、性質②より大小関係は変化しない。
よって、解法としては、すべての組み合わせ(i, j)(i < j)について、k番目のbitが、A[i]とA[j]で異なる最大のbit数であるとすると、Bのk番目のbitを1にすることで得になる/ならないで点数をつけて、すべてのbitについてそれを最大化すれば良い。ソースコード見たほうがわかりやすそう。
以下ソースコード

class XorSequenceEasy {
public:
    int getmax(vector <int> A, int N) {
        int n = A.size();
        int K = 0, cur = 1;
        int ret = 0;
        while (cur < N) {
            K++; cur <<= 1;
        }
        vector<int> point(K); // bitを1にした時良くなるスコア
        for (int i = 0; i < n; i++) {
            for (int j = i+1; j < n; j++) {
                if (A[i] < A[j]) ret++;
                for (int k = K-1; k >= 0; k--) {
                    int a = (A[i]>>k) & 1;
                    int b = (A[j]>>k) & 1;
                    if (a != b) {
                        if (a < b) point[k]--;
                        else point[k]++;
                        break;
                    }
                }
            }
        }
        for (int k = 0; k < K; k++) {
            if (point[k] > 0) ret += point[k];
        }
        return ret;
    }
};