AtCoder Regular Contest 103

來源:互聯網
上載者:User

標籤:ace   roo   section   reg   end   pen   continue   har   ==   

AtCoder Regular Contest 103一些吐槽

參加的第一場\(ARC\):一個類比 + 三個構造
沒見過比這更令人感動的題型設定了(簡直就是針對我(TAT)) 。
感覺全場就我一個人\(E\)題WA了四遍才過.......

C-////

題目大意:
網址
給定一個串\(S\),要求修改一些字元,使得串滿足以下條件:

  • \(S_i = S_{i+2}\)
  • \(S_1 \neq S_2\) 。

問最少需要修改多少個字元。
題解:
無腦統計一下奇數和偶數格的每種種類。
然後在最大值和次大值中進行抉擇即可,各種情況討論一下就行了。
代碼:

#include<bits/stdc++.h>#define IL inline#define _ 200005#define ll long longusing namespace std ;IL int gi(){    int data = 0 , m = 1; char ch = 0;    while(ch!='-' && (ch<'0'||ch>'9')) ch = getchar();    if(ch == '-'){m = 0 ; ch = getchar() ; }    while(ch >= '0' && ch <= '9'){data = (data<<1) + (data<<3) + (ch^48) ; ch = getchar(); }    return (m) ? data : -data ; }map<int,int>M[2] ;struct Item{    int val , cnt ;    bool operator < (const Item &B) const {        return (cnt ^ B.cnt) ? cnt > B.cnt : val > B.val ;     }}p[2][_] ;int n , A[_] , tot[2] , n1 , n0 , ans ; int main() {    freopen("testdata.in","r",stdin) ;    n = gi() ;    for(int i = 1; i <= n; i ++) A[i] = gi() ;    for(int i = 1; i <= n; i += 2) {        M[0][A[i]] ++ ; n0 ++ ;     }    for(int i = 2; i <= n; i += 2) {        M[1][A[i]] ++ ; n1 ++ ;     }    int p1 , p2 ;     for(map<int,int>::iterator it = M[0].begin(); it != M[0].end(); it ++) {        p[0][++tot[0]].val = it->first ;        p[0][tot[0]].cnt = it->second ;     }    for(map<int,int>::iterator it = M[1].begin(); it != M[1].end(); it ++) {        p[1][++tot[1]].val = it->first ;        p[1][tot[1]].cnt = it->second ;     }    sort(p[0] + 1 , p[0] + tot[0] + 1) ;    sort(p[1] + 1 , p[1] + tot[1] + 1) ;    if(tot[0] == 1 && tot[1] == 1) {        if(p[0][1].val == p[1][1].val) ans = min(n0 , n1) ;         else ans = 0 ;     }    else if(tot[0] == 1) {        if(p[0][1].val == p[1][1].val) {            ans = min(1 + n1 - p[1][1].cnt , n1 - p[1][2].cnt) ;         }        else ans = n1 - p[1][1].cnt ;     }    else if(tot[1] == 1) {        if(p[1][1].val == p[0][1].val) {            ans = min(1 + n0 - p[0][1].cnt , n0 - p[0][2].cnt) ;         }        else ans = n0 - p[0][1].cnt ;     }    else {        if(p[1][1].val == p[0][1].val)            ans = min(n1 - p[1][1].cnt + n0 - p[0][2].cnt , n0 - p[0][1].cnt + n1 - p[1][2].cnt) ;        else ans = n1 - p[1][1].cnt + n0 - p[0][1].cnt ;     }    cout << ans << endl ;    return 0 ; }
D-Robot Arms

網址
題目大意:
給定平面上的\(n\)個點,要求構造\(m\)個數\(d_1,d_2...d_m\),需滿足:
移動原則:從原點出發,走\(m\)步,每次可以向 上/下/左/右 走\(d_i\) 。
要求\(n\)個點都可以用 構造出的\(m\)個\(d\)通過上述方式到達。
其中構造結果有限制:\(m \leq 40\) , \(d \leq 10^{12}\),無解輸出\(-1\)。
題解:
若\(n\)個點需要移動的步數奇偶性不同顯然無解。
有個結論:用\(2^0,2^1...2^k\) 可以構造出\(2^{k+1}-1\)範圍內的所有奇數。
若需要步數為偶數,我們強行開始時移動一步,把其變為奇數的情況。
把座標系\(45\)度翻轉,然後就只需要考慮一維了。
根據上面的結論,\(d=2^0,2^1...2^{33}\),每次貪心移動到離原點較近的點即可。
代碼:

#include<bits/stdc++.h>#define IL inline#define _ 1005#define ll long longusing namespace std ;IL ll gi(){    ll data = 0 , m = 1; char ch = 0;    while(ch!='-' && (ch<'0'||ch>'9')) ch = getchar();    if(ch == '-'){m = 0 ; ch = getchar() ; }    while(ch >= '0' && ch <= '9'){data = (data<<1) + (data<<3) + (ch^48) ; ch = getchar(); }    return (m) ? data : -data ; }ll X[_],Y[_],dis[_],n,m,mx[_],my[_] ;vector<ll>Arm ;vector<char>Ans[_] ;namespace cpp600{    IL void main() {        m = 0 ;         if(dis[1] % 2 == 0) {            for(int i = 1; i <= n; i ++) {                Ans[i].push_back('R') ; X[i] -- ;                           }            m ++ ; Arm.push_back(1) ;        }        for(int i = 1; i <= n; i ++) X[i] = 2ll * X[i] , Y[i] = 2ll * Y[i] ;        for(int i = 1; i <= n; i ++) {            ll x = X[i] , y = Y[i] ;            X[i] = x + y ; Y[i] = x - y ;            X[i] >>= 1 ; Y[i] >>= 1 ;         }        //for(int i = 1; i <= n; i ++) cout << X[i] << " " << Y[i] << endl ;        m += 34 ;        for(int i = 1; i <= 34; i ++) Arm.push_back(1ll << (i - 1)) ;        for(int i = 1; i <= n; i ++) {            for(int e = 0; e <= 33; e ++) mx[e] = my[e] = 0 ;            for(int e = 33; e >= 0 ; e --) {                if(X[i] <= 0) mx[e] = 1 , X[i] += (1ll<<e) ;                else if(X[i] > 0) mx[e] = -1 , X[i] -= (1ll<<e) ;            }            for(int e = 33; e >= 0 ; e --)                if(Y[i] <= 0) my[e] = 1 , Y[i] += (1ll<<e) ;                else if(Y[i] > 0) my[e] = -1 , Y[i] -= (1ll<<e) ;             for(int e = 0; e <= 33; e ++)                if(mx[e] > 0 && my[e] > 0) Ans[i].push_back('L') ;                else if(mx[e] < 0 && my[e] < 0) Ans[i].push_back('R') ;                else if(mx[e] > 0 && my[e] < 0) Ans[i].push_back('D') ;                else if(mx[e] < 0 && my[e] > 0) Ans[i].push_back('U') ;        }        cout << m << endl ;        for(int i = 0; i < m; i ++) cout << Arm[i] << " " ;cout << endl ;        for(int i = 1; i <= n; i ++) {            for(int j = 0; j < m; j ++) cout << Ans[i][j] ;            cout << endl ;        }        return ;    }}int main() {    freopen("testdata.in","r",stdin) ;    n = gi() ;    bool flag = true ;     for(int i = 1; i <= n; i ++) {        X[i] = gi() , Y[i] = gi() ;        if(!(-10 <= X[i] && X[i] <= 10)) flag = false ;             if(!(-10 <= Y[i] && Y[i] <= 10)) flag = false ;     }    for(int i = 1; i <= n; i ++) dis[i] = abs(X[i]) + abs(Y[i]) ;    for(int i = 2; i <= n; i ++) if((dis[i]&1) != (dis[1]&1)) {puts("-1") ; return 0 ;}    cpp600::main() ;     return 0 ; }
E-Tr/ee

網址
題目大意:
給定長度為\(n\)的字串\(S\),
若\(S_i=0\)則表示不能通過割掉一條邊形成一個大小為\(i\) 的聯通塊。
若\(S_i=1\)則表示可以通過割掉一條邊形成一個大小為\(i\) 的聯通塊。
構造合格\(n\)個節點的樹,無解輸出\(-1\)。
題解:
無解情況:\(S_1=0\)、\(S_n=1\)、\(S_i\neq S_{n-i}\) 。
否則考慮\(S_i=1\) 意味著存在一個大小為\(i\) 的子樹,\(S_i=0\)則表示不存在。
考慮從小子樹開始構造,設上一次構造出的為大小為\(l\) 的子樹。
這次要構造一個大小為\(k\) 的子樹,且不能讓大小\(\in (l,k)\) 的子樹出現。
由於\(S_1 = 1\),即大小為\(1\)的點可以隨便用。
所以可以這樣:新增一個根,把大小為\(l\) 的子樹接在其下,不足的大小\(k-l-1\)全用菊花補全。
代碼:

#include<bits/stdc++.h>#define IL inline#define _#define ll long longusing namespace std ;IL int gi(){    int data = 0 , m = 1; char ch = 0;    while(ch!='-' && (ch<'0'||ch>'9')) ch = getchar();    if(ch == '-'){m = 0 ; ch = getchar() ; }    while(ch >= '0' && ch <= '9'){data = (data<<1) + (data<<3) + (ch^48) ; ch = getchar(); }    return (m) ? data : -data ; }int n,lst,lst_n,oo,fa[1000005] ; char s[1000000] ;int main() {    freopen("testdata.in","r",stdin) ;    scanf("%s" , s + 1) ;    n = strlen(s + 1) ;     if(s[1] == '0' || s[n] == '1') return puts("-1") , 0 ;    for(int i = 1; i <= n-1; i ++)        if(s[i] != s[(n-i)]) return puts("-1") , 0 ;     ++ oo ;    lst = 1 ;    int rt = oo ;     for(int i = 2; i <= n / 2; i ++) {        if(s[i] == '0') continue ;        ++ oo ;        fa[rt] = oo ;        rt = oo ;        for(int j = lst + 1; j <= i-1; j++) {            fa[++oo] = rt ;        }        lst = i ;     }    //cout << n << ": oo = "<<oo<<endl ;    fa[rt] = oo + 1 ;     int root = ++ oo ;    for(int j = oo + 1; j <= n; j ++) fa[j] = root ;    for(int i = 1; i <= n; i ++)        if(i != root) printf("%d %d\n" , i , fa[i]) ;    return 0 ; }
F-Distance Sums

網址
題目大意:
給定每個點\(i\)到其它點的距離和\(d_i\)。
構造一棵合格樹,無解輸出\(-1\),保證\(d\)兩兩不同。
題解:
考慮\(v\)和它的父親\(u\)之間的關係:\(d_u = d_v + sz_v - (n-sz_v)\)。
即我們有:\(f_u = d_v - n + 2sz_v\) 。
把\(d\)按照降序排序,顯然葉子節點的\(d\)最大,故按照降序枚舉。
我們每枚舉到一個點,根據上式可以得到其父親的\(d\)的值,對應串連即可。
若找不到合格\(d\),則無解。
注意這樣構造出來的樹不一定正確,所以最後再進行一遍樹形\(DP\)驗證構造正確性。
代碼:

#include<bits/stdc++.h>#define IL inline#define _ 1000005#define ll long longusing namespace std ;IL ll gi(){    ll data = 0 , m = 1; char ch = 0;    while(ch!='-' && (ch<'0'||ch>'9')) ch = getchar();    if(ch == '-'){m = 0 ; ch = getchar() ; }    while(ch >= '0' && ch <= '9'){data = (data<<1) + (data<<3) + (ch^48) ; ch = getchar(); }    return (m) ? data : -data ; }ll fa[_],sz[_],m,n,d[_],f[_],g[_] ; struct Item{ll id , dis ; } t[_] ; struct _Edge{int to,next ; }Edge[_<<1] ; int head[_],CNT ;  IL void AddEdge(int u , int v) {    Edge[++CNT] = (_Edge){v , head[u]} ; head[u] = CNT ;     return ;  }IL bool cmp1(Item A , Item B){    return (A.dis ^ B.dis) ? A.dis < B.dis : A.id < B.id ;  }IL bool cmp2(Item A , Item B){    return (A.id ^ B.id) ? A.id < B.id : A.dis < B.dis ;  }void dfs1(int u , int From) {    sz[u] = 1ll ;    for(int e = head[u] ; e ; e = Edge[e].next) {        int v = Edge[e].to ; if(v == From) continue ;         dfs1(v , u) ;        f[u] += f[v] + sz[v] ;         sz[u] += sz[v] ;      }    return ; }void dfs2(int u , int From) {    for(int e = head[u] ; e ; e = Edge[e].next) {        int v = Edge[e].to ; if(v == From) continue ;         g[v] = f[u] + g[u] - (f[v] + sz[v]) + (n - sz[v]) ;         dfs2(v , u) ;     }    return ; }int main() {    freopen("testdata.in","r",stdin) ;    n = gi() ;    for(int i = 1; i <= n; i ++) t[i].id = i , t[i].dis = gi() ;    sort(t + 1 , t + n + 1 , cmp1) ;    for(int i = 1; i <= n; i ++) d[i] = t[i].dis ;     d[n + 1] = 1e18 ;      for(int i = n; i > 1; i --) {        int u = t[i].id ;         sz[u] ++ ;         ll ds = t[i].dis + 2ll * sz[u] - n ;        ll ps = lower_bound(d + 1 , d + n + 2 , ds) - d ;        if(ps >= i || t[ps].dis != ds) return puts("-1") , 0 ;        fa[u] = t[ps].id ;        sz[t[ps].id] += sz[u] ;     }    sort(t + 1 , t + n + 1 , cmp2) ;     for(int i = 1; i <= n; i ++) if(fa[i]) AddEdge(fa[i],i) , AddEdge(i,fa[i]) ;     dfs1(1 , 0) ;     dfs2(1 , 0) ;     for(int i = 1; i <= n; i ++) if(f[i]+g[i] != t[i].dis) return puts("-1") , 0 ;    for(int i = 1; i <= n; i ++) if(fa[i]) cout << fa[i] << " " << i << endl ;    return 0 ; }

AtCoder Regular Contest 103

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.