D,http://acm.uestc.edu.cn/#/problem/show/1584


题意:平面上n个点,询问每个点左下方的点有多少个?

解法:排序(以Y坐标为第一关键字,X坐标为第二关键字)+树状数组


#include <bits/stdc++.h>
using namespace std;
const int maxn=100010;
int n,rnk[maxn],c[maxn];
struct node{
    int x,y;
}a[maxn];
bool cmp(node x, node y){
    if(x.y==y.y) return x.x<y.x;
    return x.y<y.y;
}
inline int lowbit(int x){
    return x&-x;
}
void add(int x){
    while(x<maxn){
        c[x]++;
        x+=lowbit(x);
    }
}
int sum(int x){
    int ans=0;
    while(x>0){
        ans+=c[x];
        x-=lowbit(x);
    }
    return ans;
}
int main()
{
    int n;
    while(~scanf("%d",&n)){
        for(int i=1; i<=n; i++) scanf("%d %d", &a[i].x,&a[i].y);
        sort(a+1,a+n+1,cmp);
        memset(rnk,0,sizeof(rnk));
        memset(c,0,sizeof(c));
        for(int i=1; i<=n; i++){
            rnk[sum(a[i].x)]++;
            add(a[i].x);
        }
        for(int i=1; i<n; i++) printf("%d\n", rnk[i-1]);
        printf("%d\n", rnk[n-1]);
    }
    return 0;
}


E,http://acm.uestc.edu.cn/#/problem/show/1583

题意:一个排列,用最少的交换次数次数变换到另一个排列,每次只能交换相邻两个元素。

解法:处理一个数组d,d[i]表示a[i]应该到b数组哪个位置。答案就是d数组的逆序对数

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
typedef long long LL;
int n,a[maxn],c[maxn];
void add(int x){
    while(x<maxn){
        c[x]++;
        x+=x&-x;
    }
}
int sum(int x){
    int ans=0;
    while(x>0){
        ans+=c[x];
        x-=x&-x;
    }
    return ans;
}

int main()
{
    while(~scanf("%d",&n)){
        memset(c,0,sizeof(c));
        memset(a,0,sizeof(a));
        LL ans=0;
        for(int i=1; i<=n; i++){
            int x; scanf("%d", &x); a[x]=i;
        }
        for(int i=1; i<=n; i++){
            int x; scanf("%d", &x);
            ans+=1LL*(sum(n)-sum(a[x]-1));
            add(a[x]);
        }
        printf("%lld\n", ans);
    }
    return 0;
}

F,http://acm.uestc.edu.cn/#/problem/show/1582

题意:给你n个元素的数组{a},m次询问,每次给你一个数X,每次问你max{a1 xor X, a2 xor X, …, an xor X}

解法:对{a}里每个元素的二进制串从高位到低位建立trie(零一字典树)
询问时贪心(显然,让更高位的二进制位为1是要更优的)地向下,如果x该位是1,那么走0,如果是0,那么走1。
如果该位仅有1或0,那没办法,只能往这里走。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e7+2;
struct node{
    int root,tot,ch[maxn][2];
    int newnode(){
        ch[tot][0]=ch[tot][1]=-1;
        return tot++;
    }
    void init(){
        tot=0,root=newnode();
    }
    void Insert(int x){
        int now=root;
        for(int j=30; j>=0; j--){
            int go=(x&(1<<j))?1:0;
            if(ch[now][go]==-1){
                ch[now][go]=newnode();
                now=ch[now][go];
            }
            else{
                now=ch[now][go];
            }
        }
    }
    int query(int x){
        int now=root;
        int ans=0;
        for(int j=30; j>=0; j--){
            int go=(x&(1<<j))?1:0;
            if(ch[now][!go]!=-1) ans|=(1<<j),now=ch[now][!go];
            else now=ch[now][go];
        }
        return ans;
    }
}trie;
int main()
{
    int n, q;
    while(~scanf("%d",&n)){
        trie.init();
        for(int i=1; i<=n; i++){
            int x;
            scanf("%d",&x);
            trie.Insert(x);
        }
        scanf("%d",&q);
        while(q--){
            int x;
            scanf("%d", &x);
            printf("%d\n", trie.query(x));
        }
    }
    return 0;
}