AtCoderARC022

Posted ivorysi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoderARC022相关的知识,希望对你有一定的参考价值。

C - Multiple Gift

题解

首项是X,每次乘个2,暴力统计

代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define mp make_pair
#define pb push_back
#define enter putchar(‘
‘)
#define space putchar(‘ ‘)
#define eps 1e-8
#define mo 974711
#define MAXN 2005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < ‘0‘ || c > ‘9‘) {
    if(c == ‘-‘) f = -1;
    c = getchar();
    }
    while(c >= ‘0‘ && c <= ‘9‘) {
    res = res * 10 + c - ‘0‘;
    c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar(‘-‘);}
    if(x >= 10) {
    out(x / 10);
    }
    putchar(‘0‘ + x % 10);
}
int64 X,Y;

int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    read(X);read(Y);
    int l = 1;
    while(X <= Y / 2) {++l;X *= 2;}
    out(l);enter;
}

D - Wide Flip

题解

从大到小枚举K(也可以二分)
如果(2K <= N),此时(K)一定合法
否则看前(K)个和后(K)个交出来的中间一段,这段的前面和后面1和0是可以单个位置随便改的(用一次K + 1的区间再用一次K的区间)
只要看中间一段是不是全1或者全0即可

代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define mp make_pair
#define pb push_back
#define enter putchar(‘
‘)
#define space putchar(‘ ‘)
#define eps 1e-8
#define mo 974711
#define MAXN 2005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < ‘0‘ || c > ‘9‘) {
    if(c == ‘-‘) f = -1;
    c = getchar();
    }
    while(c >= ‘0‘ && c <= ‘9‘) {
    res = res * 10 + c - ‘0‘;
    c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar(‘-‘);}
    if(x >= 10) {
    out(x / 10);
    }
    putchar(‘0‘ + x % 10);
}
char s[1000005];
int sum[100005],N;
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    scanf("%s",s + 1);
    N = strlen(s + 1);
    for(int i = 1 ; i <= N ; ++i) {
    sum[i] = sum[i - 1];
    if(s[i] == ‘1‘) sum[i]++;
    }
    for(int K = N ; K >= 1 ; --K) {
    int r = K;
    int l = N - K + 1;
    if(l > r) {
        out(K);enter;return 0;
    }
    if(sum[r] - sum[l - 1] == 0 || sum[r] - sum[l - 1] == r - l + 1) {
        out(K);enter;return 0;
    }
    }
}

E - Papple Sort

题解

只要每次把靠边的一个字符的匹配点找出来同样后移然后一起删除即可
就是讨论一下
...A...A...B...B..
A要和这个一对B交换两次
B如果要过去也要换两次,所以都一样
A..B..A..B
A要和B换一次,如果B到外面也是和A换一次,所以都一样
树状数组维护一下前缀有多少数即可

代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define mp make_pair
#define pb push_back
#define enter putchar(‘
‘)
#define space putchar(‘ ‘)
#define eps 1e-8
#define mo 974711
#define MAXN 200005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < ‘0‘ || c > ‘9‘) {
    if(c == ‘-‘) f = -1;
    c = getchar();
    }
    while(c >= ‘0‘ && c <= ‘9‘) {
    res = res * 10 + c - ‘0‘;
    c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar(‘-‘);}
    if(x >= 10) {
    out(x / 10);
    }
    putchar(‘0‘ + x % 10);
}
char s[MAXN];
int N;
vector<int> c[30];
bool vis[MAXN];
int tr[MAXN];
void Init() {
    scanf("%s",s + 1);
    N = strlen(s + 1);
}
int lowbit(int x) {return x & -x;}
void Insert(int x,int v) {
    while(x <= N) {
    tr[x] += v;
    x += lowbit(x);
    }
}
int Query(int x) {
    int res = 0;
    while(x > 0) {
    res += tr[x];
    x -= lowbit(x);
    }
    return res;
} 
void Solve() {
    int cnt = 0;
    for(int i = N ; i >= 1 ; --i) {
    c[s[i] - ‘a‘].pb(i);
    }
    for(int i = 0 ; i < 26 ; ++i) {
    if(c[i].size() & 1) ++cnt;
    }
    if(cnt >= 2) {puts("-1");return;}
    for(int i = 1 ; i <= N ; ++i) Insert(i,1);
    int64 ans = 0;
    int k = 0;
    for(int i = N ; i >= 1 ; --i) {
    if(vis[i]) continue;
    int t = c[s[i] - ‘a‘].back();c[s[i] - ‘a‘].pop_back();
    if(t == i){ ++k;continue;}
    ans += Query(t - 1) + k;
    vis[t] = 1;
    Insert(t,-1);
    }
    out(ans);enter;
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Init();
    Solve();
}

F - Christmas Tree

题解

啊这个只要dp一下第一个值再二分。。。二分判的方法是……
woc这不NOIPD1T3啊怎么一模一样啊

代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define mp make_pair
#define pb push_back
#define enter putchar(‘
‘)
#define space putchar(‘ ‘)
#define eps 1e-8
#define mo 974711
#define MAXN 100005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < ‘0‘ || c > ‘9‘) {
    if(c == ‘-‘) f = -1;
    c = getchar();
    }
    while(c >= ‘0‘ && c <= ‘9‘) {
    res = res * 10 + c - ‘0‘;
    c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar(‘-‘);}
    if(x >= 10) {
    out(x / 10);
    }
    putchar(‘0‘ + x % 10);
}
int N;
struct node {
    int to,next;
}E[MAXN * 2];
int head[MAXN],sumE;
int dp[MAXN],A,lim,res;
int val[MAXN],tot;
bool vis[MAXN];
void add(int u,int v) {
    E[++sumE].to = v;
    E[sumE].next = head[u];
    head[u] = sumE;
}
void Init() {
    read(N);
    int a,b;
    for(int i = 1 ; i < N ; ++i) {read(a);read(b);add(a,b);add(b,a);}
    
}
void dfs(int u,int fa) {
    int son = 0;
    for(int i = head[u] ; i ; i = E[i].next) {
    int v = E[i].to;
    if(v != fa) {
        dfs(v,u);
        ++son;
        dp[u] += dp[v];
    }
    }
    dp[u] -= son / 2;
    if(son % 2 == 0 && fa) dp[u]++;
}
struct BIT {
    int tr[MAXN],s;
    void clear() {
    for(int i = 1 ; i <= s ; ++i) tr[i] = 0;
    }
    int lowbit(int x) {return x & -x;}
    int query(int x) {
    int res = 0;
    while(x > 0) {
        res += tr[x];
        x -= lowbit(x);
    }
    return res;
    }
    void insert(int x,int v) {
    while(x <= s) {
        tr[x] += v;
        x += lowbit(x);
    }
    }
    int find_max() {
    int L = 1,R = s;
    int x = query(s);
    if(x == 0) return 0;
    while(L < R) {
        int m = (L + R + 1) >> 1;
        if(query(m - 1) != x) L = m;
        else R = m - 1;
    }
    return L;
    }
}BST;
void calc(int u,int fa) {
    for(int i = head[u] ; i ; i = E[i].next) {
    int v = E[i].to;
    if(v != fa) {
        calc(v,u);
    }
    }
    tot = 0;
    for(int i = head[u] ; i ; i = E[i].next) {
    int v = E[i].to;
    if(v != fa) {
        val[++tot] = dp[v];
    }
    }
    if(!tot) {dp[u] = 1;++res;return;}
    BST.clear();
    sort(val + 1,val + tot + 1);
    for(int i = 1 ; i <= tot ; ++i) vis[i] = 1;
    BST.s = tot;int p = 0;
    for(int i = tot ; i >= 1 ; --i) {
    if(!vis[i]) continue;
    while(p < i && val[p + 1] + val[i] <= lim) {
        ++p;BST.insert(p,1);
    }
    if(p >= i) BST.insert(i,-1);
    int t = BST.find_max();
    if(t) {vis[t] = 0;vis[i] = 0;BST.insert(t,-1);--res;}
    }
    if(fa) {
    dp[u] = 1;++res;
    for(int i = 1 ; i <= tot ; ++i) {
        if(vis[i]) {
        if(val[i] + 1 > lim) break;
        dp[u] += val[i];--res;
        break;
        }
    }
    }
}
bool check(int m) {
    lim = m;res = 0;
    calc(1,0);
    return res <= A;
}
void Solve() {
    dfs(1,0);
    out(dp[1]);space;
    A = dp[1];
    int L = 1,R = N - 1;
    while(L < R) {
    int mid = (L + R) >> 1;
    if(check(mid)) R = mid;
    else L = mid + 1;
    }
    out(R);enter;
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Init();
    Solve();
}











以上是关于AtCoderARC022的主要内容,如果未能解决你的问题,请参考以下文章

AtCoderARC094(C-F)题解

AtCoderARC096(C - F)

AtCoderARC096 C-F题解

AtCoderARC 098 F - Donation

AtcoderARC062F Painting Graphs with AtCoDeer 双连通分量polya原理

AtCoderARC100 题解