zoukankan      html  css  js  c++  java
  • 【AtCoder】AGC007

    AGC007

    A - Shik and Stone

    如果i + j走过的格子只有一个,那么就是可以走到

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define eps 1e-10
    #define MAXN 100005
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;T f = 1;char c = getchar();
        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 H,W,cnt[30];
    char s[15][15];
    bool vis[15][15];
    void Solve() {
        read(H);read(W);
        for(int i = 1 ; i <= H ; ++i) {
            scanf("%s",s[i] + 1);
        }
        for(int i = 1 ; i <= H ; ++i) {
            for(int j = 1 ; j <= W ; ++j) {
                if(s[i][j] == '#') {
                    ++cnt[i + j];
                    if(cnt[i + j] >= 2) {puts("Impossible");return;}
                }
            }
        }
        puts("Possible");
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
        return 0;
    }
    

    B - Construct Sequences

    把a标成(i*N)

    把b标成((N - i + 1) * N)

    此时a和b按位相加后相等,然后按照排列的顺序,给第一个排列所在的b加0,第二个+1,第三个+2...就可以了

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define eps 1e-10
    #define MAXN 205
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;T f = 1;char c = getchar();
        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;
    int a[20005],b[20005],p[20005];
    void Solve() {
        read(N);
        for(int i = 1 ; i <= N ; ++i) read(p[i]);
        for(int i = 1 ; i <= N ; ++i) {b[i] = (N - i + 1) * N; a[i] = i * N;}
        for(int i = 1 ; i <= N ; ++i) {
    	b[p[i]] += i - 1;
        }
        for(int i = 1 ; i <= N ; ++i) {
    	out(a[i]);space;
        }
        enter;
        for(int i = 1 ; i <= N ; ++i) {
    	out(b[i]);space;
        }
        enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
        return 0;
    }
    

    C - Pushing Balls

    这个需要注意到,当我们一个球进洞后,其余的球还是原来的形态,且差距(d_{i})仍然是一个等差数列

    我们每次的期望就是(frac{2nd + 2n(2n - 1)x/2}{2n} = d + (2n - 1)x / 2)

    推一下式子发现新的首项是

    (d' = (n + 1)d/ n + 5x /2n)

    (x' = (n + 2)x / n)

    然后(n - 1),继续计算

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define eps 1e-10
    #define MAXN 205
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;T f = 1;char c = getchar();
        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;
    db d,x;
    void Solve() {
        read(N);
        scanf("%lf%lf",&d,&x);
        db ans = 0;
        while(N) {
    	ans += d + (2 * N - 1) / 2.00 * x;
    	d = 1.0 * (N + 1) / N * d + 5 * x / (2 * N);
    	x = 1.0 * (N + 2) / N * x;
    	--N;
        }
        printf("%.10lf
    ",ans);
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
        return 0;
    }
    

    D - Shik and Game

    相当于除掉我必须从0走到1的点,我在上面需要绕几个环

    很显然,环是互相分离的,因为如果环的最靠前一个点有钱,走回去的路上钱都会被捡起来

    这样就很容易dp了,我们可以把E去掉,求附加的最小时间

    (dp[i])表示走到i且i的钱被捡完了的最小附加时间

    如果从前面一个(j)转移过来,若(2(x[i] - x[j]) >= T),那么这一圈的附加时间应该是(2(x[i] - x[j])),否则应该是T

    这两个分别可以用前缀最小值和单调队列维护,复杂度(O(n))

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define eps 1e-10
    #define MAXN 205
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;T f = 1;char c = getchar();
        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 dp[100005],pre;
    int64 T,E;
    int64 x[100005];
    int N,p;
    deque<int> que;
    void Solve() {
        read(N);read(E);read(T);
        for(int i = 1 ; i <= N ; ++i) {read(x[i]);dp[i] = i * T;}
        p = -1;pre = 1e18;
        que.push_back(0);
        for(int i = 1 ; i <= N ; ++i) {
    	while(p < i - 1 && 2 * (x[i] - x[p + 2]) > T) {
    	    ++p;pre = min(pre,dp[p] - 2 * x[p + 1]);
    	}
    	dp[i] = min(dp[i],pre + 2 * x[i]);
    	while(!que.empty() && 2 * (x[i] - x[que.front() + 1]) > T ) {que.pop_front();}
    	if(!que.empty()) {
    	    dp[i] = min(dp[i],dp[que[0]] + T);
    	}
    	while(!que.empty() && dp[que.back()] > dp[i]) que.pop_back();
    	que.push_back(i);
        }
        out(dp[N] + E);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
        return 0;
    }
    

    E - Shik and Travel

    我们记录一个点对为这棵子树中往上延伸的两条链长度((a,b))我们合并的时候用两个子树里的((a,b))((c,d))合并,二分答案来限制合并的链长不超过某个值

    合并的时候用含点对少的和含点对多的合并,新合出来的不会超过点对少的的两倍,少的中每一个点对((a,b))可以找到((a,u)),u是另一棵树能合出来最小的,b同理

    这样就可以做了

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define eps 1e-10
    #define MAXN 200005
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;T f = 1;char c = getchar();
        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;
    int64 val[MAXN],lim,pre[MAXN];
    vector<int> son[MAXN];
    vector<pair<int64,int64> > v[MAXN];
    vector<pair<int64,int64> > tmp,ano;
    bool flag = 0;
    void dfs(int u) {
        if(flag) return;
        v[u].clear();
        if(son[u].size() == 0) {v[u].pb(mp(0,0));return;}
        dfs(son[u][0]);dfs(son[u][1]);
        int a = son[u][0],b = son[u][1];
        if(v[a].size() > v[b].size()) swap(a,b);
        tmp.clear();ano.clear();
        for(auto t : v[a]) {
    	tmp.pb(mp(t.fi,t.se));tmp.pb(mp(t.se,t.fi));
        }
        sort(tmp.begin(),tmp.end());
        for(auto t : v[b]) {
    	    ano.pb(mp(t.fi,t.se));ano.pb(mp(t.se,t.fi));
        }
        sort(ano.begin(),ano.end());
        int r = ano.size() - 1;
        pre[0] = ano[0].se;
        for(int i = 1 ; i < ano.size() ; ++i) pre[i] = min(pre[i - 1],ano[i].se);
        for(auto t : tmp) {
    	while(r >= 0 && ano[r].fi + val[b] + t.fi + val[a] > lim) --r;
    	if(r >= 0) {
    	    v[u].pb(mp(pre[r] + val[b],t.se + val[a]));
    	}
        }
        if(!v[u].size()) flag = 1;
        return;
    }
    bool check(int64 mid) {
        lim = mid;
        flag = 0;dfs(1);
        if(flag) return false;
        return true;
    }
    void Solve() {
        read(N);
        int a;
        for(int i = 1 ; i < N ; ++i) {
    	read(a);
    	son[a].pb(i + 1);read(val[i + 1]);
        }
        int64 L = 0,R = 1e16;
        while(L < R) {
    	int64 mid = (L + R) >> 1;
    	if(check(mid)) {
    	    R = mid;
    	}
    	else L = mid + 1;
        }
        out(L);enter;
    }
    
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
        return 0;
    }
    

    F - Shik and Copying String

    我们先对每个点找一个匹配点,这个点就是(t[i] == s[j])且j最小的位置

    且对于i的匹配点必须是递增的

    然后我们相当于从每个匹配点在一个高度无限,宽度为字符串长度,开始每步第一次可以往下走,然后往右走,直到走到匹配的最后一个位置

    我们要求的就是这列路径的最大高度

    从后往前开始递推,遇到一个结束位置,高度加1,而且所有的下降位置需要+1

    如果这一列位置是个下降位置,上面还有c条线,我可以拖到i - c的位置再下降(咕咕咕是人类的本质)

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define space putchar(' ')
    #define enter putchar('
    ')
    #define eps 1e-10
    #define MAXN 1000005
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef unsigned int u32;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;T f = 1;char c = getchar();
        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;
    char s[MAXN],t[MAXN];
    int pos[MAXN],suf[MAXN],to[MAXN],turn[MAXN];
    void Solve() {
        read(N);
        scanf("%s",s + 1);
        scanf("%s",t + 1);
        bool f = 1;
        for(int i = 1 ; i <= N ; ++i) {
    	if(s[i] != t[i]) {f = 0;break;}
        }
        if(f) {puts("0");return;}
        int p = N;
        for(int i = N ; i >= 1 ; --i) {
    	p = min(p,i);
    	while(p >= 1 && s[p] != t[i]) --p;
    	if(p == 0) {puts("-1");return;}
    	if(!pos[p]) pos[p] = i;
    	to[i] = p;
        }
        int cnt = 0,t = 0;
        int ans =  0;
        for(int i = N ; i >= 1 ; --i) {
    	suf[i] = suf[i + 1];
    	if(pos[to[i]] == i) {
    	    ++suf[i];++cnt;++t;
    	}
    	ans = max(suf[i],ans);
    	if(pos[i]) {
    	    --cnt;
    	    turn[i - cnt + t]++;
    	}
    	suf[i] -= turn[i + t];turn[i + t] = 0;
        }
        out(ans);enter;
    }
    
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
        return 0;
    }
    
  • 相关阅读:
    WPF程序设计 :第四章 按钮与其他控件(Buttons and Other Controls)
    C#参考 : 枚举类型
    C#3.0 新特性学习笔记(3):匿名类型
    F#语言2008年9月CTP版已经更新
    C#3.0 新特性学习笔记(1): 对象集合初始化器
    WPF程序设计基础:属性系统
    C#3.0 新特性学习笔记(2):var 隐式声明变量
    MSSql行列转换的Sql语法 详解与实例
    WPF程序设计 :第一章 应用程序和窗口(The Application and the Window)
    WPF程序设计 :第二章 基本画刷(Basic Brushes)
  • 原文地址:https://www.cnblogs.com/ivorysi/p/10873406.html
Copyright © 2011-2022 走看看