2019DX#5

Solved Pro.ID Title Ratio(Accepted / Submitted)
  1001 fraction                  辗转相除 4.17%(7/168)
ok  1002 three arrays                字典树+贪心 12.69%(76/599)
  1003 geometric problem 1.59%(1/63)
  1004 equation 20.65%(310/1501)
  1005 permutation 1 24.77%(407/1643)
  1006 string matching 23.12%(724/3131)
  1007 permutation 2 47.19%(688/1458)
 ok 1008 line symmetric                 计算几何 1.87%(11/588)
  1009 discrete logarithm problem        离散对数 18.42%(7/38)
  1010 find hidden array             贪心 6.25%(2/32)

1002 three arrays

题意

给定两个长度为1e5的数组$a_1,a_2,...a_n$、$b_1,b_2,...b_n$,重新排列,使得$a_i oplus b_i $的字典序最小。

$0 le a_i , b_i < 2^{30}$

思路

对a数组和b数组建立两个字典树,然后遍历n次这两个字典树,每次两个指针分别从两颗字典树移动,能同时向0走就走,能同时向1走就向1走,每次走到底层后就是一个答案。

// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;

template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}

/**********showtime************/
            const int maxn = 1e5+9;
            int a[maxn],b[maxn];
            int tot[2],rt[2];
            int bz[33];
            struct node{
                int ch[2];
                int fa;
                int sz;
                void init(int f) {
                    ch[0] = ch[1] = 0;
                    fa = f;
                    sz = 0;
                }
            }tree[2][maxn * 30];
            int shu[35];

            void add(int p, int len, int flag) {
                if(len == 0){
                    tree[flag][p].sz++;
                    return;
                }

                if(tree[flag][p].ch[shu[len]] == 0)
                {
                    tree[flag][p].ch[shu[len]] = ++ tot[flag];
                    tree[flag][tot[flag]].init(p);
                }
                int nx = tree[flag][p].ch[shu[len]];
                add(nx, len-1, flag);
                int lc = tree[flag][p].ch[0];
                int rc = tree[flag][p].ch[1];
                tree[flag][p].sz = tree[flag][lc].sz + tree[flag][rc].sz;
            }
            void insert(int val, int flag) {
                int len = 0;
                for(int i=0; i<=30; i++) shu[++len] = val % 2, val /= 2;
                add(rt[flag], 30, flag);
            }
            void display(int rt, int flag) {
                if(rt == 0) return ;
//                cout<<tree[flag][rt].sz<<endl;
                display(tree[flag][rt].ch[0], flag);
                display(tree[flag][rt].ch[1], flag);
            }
            vector<int>vec;
            void find(int a, int b, int cen, int val) {
                if(cen == 0) {
                    vec.pb(val);
                    tree[0][a].sz--;
                    tree[1][b].sz--;
                    return;
                }
                if(tree[0][ tree[0][a].ch[0] ].sz && tree[1][ tree[1][b].ch[0]].sz ) {
                    find(tree[0][a].ch[0], tree[1][b].ch[0], cen-1, val);
                }
                else if(tree[0][ tree[0][a].ch[1] ].sz && tree[1][ tree[1][b].ch[1]].sz) {
                    find(tree[0][a].ch[1], tree[1][b].ch[1], cen-1, val);
                }
                else if(tree[0][tree[0][a].ch[0]].sz && tree[1][ tree[1][b].ch[1]].sz){
                    find(tree[0][a].ch[0], tree[1][b].ch[1], cen-1, val + bz[cen-1]);
                }
                else {
                    find(tree[0][a].ch[1], tree[1][b].ch[0], cen-1, val + bz[cen-1]);
                }

                tree[0][a].sz = tree[0][tree[0][a].ch[0]].sz + tree[0][tree[0][a].ch[1]].sz;
                tree[1][b].sz = tree[1][tree[1][b].ch[0]].sz + tree[1][tree[1][b].ch[1]].sz;

            }
int main(){
            int T;  scanf("%d", &T);
            bz[0] = 1;
            for(int i=1; i<=30; i++) bz[i] = 2 * bz[i-1];
            while(T--) {
                tot[0] = tot[1] = 0;
                rt[0] = ++tot[0];
                tree[0][rt[0]].init(0);
                rt[1] = ++tot[1];
                tree[1][rt[1]].init(0);

                int n;  scanf("%d", &n);
                for(int i=1; i<=n; i++) scanf("%d", &a[i]), insert(a[i], 0);
                for(int i=1; i<=n; i++) scanf("%d", &b[i]), insert(b[i], 1);

                vec.clear();
                for(int i=1; i<=n; i++) {
                    find(rt[0], rt[1], 30, 0);
                }
                sort(vec.begin(), vec.end());
                for(int i=0; i<vec.size() - 1; i++) printf("%d ", vec[i]);
                printf("%d
", vec[vec.size() - 1]);
//                display(rt[0], 0);
            }
            return 0;
}
View Code

1008 line symmetric

题意

给定一个多边形,定点最多有1000个,在最多移动一个点的情况下,此多边形是否能成为轴对称图形,变换后图形要保证是简单多边形。

思路

1)枚举相邻点,和间隔为2的两个点,令他们的中垂线为对称轴,判断是否可行。

2)注意点是,一个点如果在枚举的对称轴上,那么就是不可行的。

3)如果两个点如果在对称轴的两边,且要相互交换位子,那么这也是不可行的。

// #pragma GCC optimize(2)
// #pragma GCC optimize(3)
// #pragma GCC optimize(4)
#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
// #include<bits/extc++.h>
// using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;

template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}

/**********showtime************/
            const int maxn = 1e3+9;
            pii po[maxn];
            int n;
            bool dc(int le, int ri, pii m, pii k){
                // 判垂直
                int a = (po[ri].se - po[le].se) * k.se;
                int b = (po[ri].fi - po[le].fi) * k.fi;
                if(a != -b) return false;

                // 判中点
                pii mid;
                mid.fi = (po[le].fi + po[ri].fi) / 2;
                mid.se = (po[le].se + po[ri].se) / 2;

                if(k.fi == 0) {
                    return mid.fi == m.fi;
                }
                a = mid.se * k.fi;
                b = k.se * mid.fi + m.se * k.fi - k.se * m.fi;
                return a == b;
            }

            bool gao(int p1, int p2, pii m, pii k) {
                if(k.fi == 0) {
                    return (po[p1].fi - m.fi) * (po[p2].fi - m.fi) <= 0;
                }
                int tmp1 = po[p1].se * k.fi - k.se * po[p1].fi  + m.se * k.fi- k.se * m.fi;
                int tmp2 = po[p2].se * k.fi - k.se * po[p2].fi  + m.se * k.fi- k.se * m.fi;
                return 1ll*tmp1 * tmp2 <= 0;
            }
            bool check(int le, int ri) {
                int sl = le, sr = ri;
                pii m, k;

                m.fi = (po[le].fi + po[ri].fi) / 2;
                m.se = (po[le].se + po[ri].se) / 2;
                k.fi = po[ri].se - po[le].se;
                k.se = -1*(po[ri].fi - po[le].fi);
                int cnt = 0;

                for(int i=1; i <= (n+1) / 2; i++){
                    if(gao(sl, le, m, k)  && gao(sr, ri, m, k) ) return false;
                    if(dc(le, ri, m, k) == 0) cnt++;

                    ri++; if(ri == n+1) ri = 1;
                    le--; if(le == 0) le = n;
                }
                return cnt <= 1;
            }

            bool check1(int le, int ri, int mid) {
                int sl = le, sr = ri;
                pii m, k;
                m.fi = (po[le].fi + po[ri].fi) / 2;
                m.se = (po[le].se + po[ri].se) / 2;
                k.fi = po[ri].se - po[le].se;
                k.se = -1*(po[ri].fi - po[le].fi);
                // cout<<m.fi<<" , "  << m.se<<endl;
                // cout<<k.fi<<" , "  << k.se<<endl;
                int cnt = 0;
                for(int i=1; i <= n / 2; i++){
                    if(gao(sl, le, m, k) && gao(sr, ri, m, k)) return false;
                    if(dc(le, ri, m, k) == 0) cnt++;

                    ri++; if(ri == n+1) ri = 1;
                    le--; if(le == 0) le = n;
                }

                if(dc(mid, mid, m, k) == 0) cnt++;
                return cnt <= 1;
            }
int main(){
            int T;  scanf("%d", &T);
            while(T--) {
                scanf("%d", &n);
                for(int i=1; i<=n; i++) {
                    scanf("%d%d", &po[i].fi, &po[i].se);
                    po[i].fi *= 2;
                    po[i].se *= 2;
                }
                if(n <= 4) {
                    puts("Y");
                    continue;
                }
                int flag = 0;

                for(int i=1; i<=n; i++) {
                    int nx = (i + 1) ; if(nx == n+1) nx = 1;
                    int la = i - 1 ; if(!la) la = n;
                    int mid = i;
                    if(check1(la,nx, mid)) flag = 1;
                }
                for(int i=1; i<=n; i++) {
                    int cur = i;
                    int nx = i + 1; if(nx == n+1) nx = 1;
                    if(check(cur, nx)) flag = 1;
                }

                if(flag) puts("Y");
                else puts("N");
            }
            return 0;
}
/*
5
-100 -100
0 0
-100 100
1 0
100 1
*/
View Code
原文地址:https://www.cnblogs.com/ckxkexing/p/11305916.html