zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    “回调地址”全攻略 java程序员
    超棒的纯Javascript实现的文件上传功能 Fine uploader java程序员
    帮助你操作数字和处理数字格式的javascript类库 Numeral.js java程序员
    正则表达式 java程序员
    一款非常棒的CSS 3D下拉式菜单实现Makisu java程序员
    Google的全新在线地图API演示网站 More than a map java程序员
    Android中的布局属性 java程序员
    整理一系列优秀的Android开发源码 java程序员
    Lambda表达式select()和where()的区别
    按公式产生随机数、java中的重载、递归、有关计算机计算的问题
  • 原文地址:https://www.cnblogs.com/ckxkexing/p/11305916.html
Copyright © 2011-2022 走看看