2015-2016 ACM-ICPC, NEERC, Northern Subregional Contest

A-Alex Origami Squares

水题。

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define xx first
#define yy second
#define LL long long
#define MP make_pair
#define INF 0x3f3f3f3f
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))

using namespace std;

int main()
{
    freopen("alex.in", "r", stdin);
    freopen("alex.out", "w", stdout);
    double n, m;
    while(cin >> n >> m)
    {
        double mxx = 0;
        mxx = max(mxx, min(m, n / 3));
        mxx = max(mxx, min(n, m / 3));
        mxx = max(mxx, min(m / 2, n / 2));
        printf("%.3f\n", mxx);
    }
    return 0;
}

B- Black and White

不知道题意。

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define xx first
#define yy second
#define LL long long
#define MP make_pair
#define INF 0x3f3f3f3f
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))

using namespace std;

int main () {
    freopen("black.in", "r", stdin);
    freopen("black.out", "w", stdout);
    int a, b;
    while(cin >> a >> b) {
        char x = '.';
        char y = '@';
        if(a < b) {
            swap(x, y);
            swap(a, b);
        }
//        printf("duo %c shao %c\n", x, y);
        b --;
        int dt = (a - b);
        a -= dt;
        int r = dt * 2 + 1 + a + b;
        int c = 2;
        printf("%d %d\n", r, c);
        printf("%c%c\n", x, x);
        for(int i = 0; i < dt; i ++) {
            printf("%c%c\n", x, y);
            printf("%c%c\n", x, x);
        }
        while(a || b) {
            if(b) printf("%c%c\n", y, y), b --;
            if(a) printf("%c%c\n", x, x), a --;
        }
    }
    return 0;
}

C- Concatenation

给两个字符串s1,s2,求s1的前缀和s2的后缀拼接可以有多少种不同的子串。

总数减去s2中的子串可以作为s1子串的个数就好了。这个可以用后缀数组实现。

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define xx first
#define yy second
#define LL long long
#define MP make_pair
#define INF 0x3f3f3f3f
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))

using namespace std;

const int maxn = 211111;

char ch1[maxn], ch2[maxn];
struct SuffixArray
{
    int r[maxn];
    int sa[maxn], rank[maxn], height[maxn];
    int t[maxn], t2[maxn], c[maxn], n;
    int m;
    void init(char* s)
    {
        n = strlen(s);
        for (int i = 0; i < n; i++) r[i] = int(s[i]);
        r[n] = 0;
        m = 300;
    }
    int cmp(int *r, int a, int b, int l)
    {
        return r[a] == r[b] && r[a + l] == r[b + l];
    }
    void build_sa()
    {
        int i, k, p, *x = t, *y = t2;
        r[n++] = 0;
        for (i = 0; i < m; i++) c[i] = 0;
        for (i = 0; i < n; i++) c[x[i] = r[i]]++;
        for (i = 1; i < m; i++) c[i] += c[i - 1];
        for (i = n - 1; i >= 0; i--) sa[--c[x[i]]] = i;
        for (k = 1, p = 1; k < n; k *= 2, m = p)
        {
            for (p = 0, i = n - k; i < n; i++) y[p++] = i;
            for (i = 0; i < n; i++) if (sa[i] >= k) y[p++] = sa[i] - k;
            for (i = 0; i < m; i++) c[i] = 0;
            for (i = 0; i < n; i++) c[x[y[i]]]++;
            for (i = 1; i < m; i++) c[i] += c[i - 1];
            for (i = n - 1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
            swap(x, y);
            p = 1;
            x[sa[0]] = 0;
            for (i = 1; i < n; i++) x[sa[i]] = cmp(y, sa[i - 1], sa[i], k) ? p - 1 : p++;
        }
        n--;
    }
    void getHeight()
    {
        int i, j, k = 0;
        for (i = 1; i <= n; i++) rank[sa[i]] = i;
        for (i = 0; i < n; i++)
        {
            if (k) k--;
            j = sa[rank[i] - 1];
            while (r[i + k] == r[j + k]) k++;
            height[rank[i]] = k;
        }
    }
    int d[maxn][20];
    void RMQ_init(int A[], int n)
    {
        for (int i = 1; i <= n; i++) d[i][0] = A[i];
        for (int j = 1; (1 << j) <= n; j++)
            for (int i = 1; i + (1 << (j - 1)) <= n; i++)
                d[i][j] = min(d[i][j - 1], d[i + (1 << (j - 1))][j - 1]);
    }
    int RMQ(int L, int R)
    {
        int k = 0;
        while ((1 << (k + 1)) <= R - L + 1) k++;
        return min(d[L][k], d[R - (1 << k) + 1][k]);
    }
    void LCP_init()
    {
        RMQ_init(height, n);
    }
    int lcp(int i, int j)
    {
        if(i == j) return 1;
        if (rank[i] > rank[j]) swap(i, j);
        return RMQ(rank[i] + 1, rank[j]);
    }
    void call_fun(char* s)
    {
        init(s);
        build_sa();
        getHeight();
        LCP_init();
    }
    LL solve(int len)
    {
        LL ret = 0;
        int l = 1, r = 0, tmp = 0;
        for(int i = 1; i <= n; i ++)
        {
            while(l < i && lcp(sa[l], sa[i]) == 0)
            {
                if(sa[l] > 0 && sa[l] < len) tmp --;
                l ++;
            }
            while(r < n && lcp(sa[i], sa[r + 1]) > 0)
            {
                r ++;
                if(sa[r] > 0 && sa[r] < len) tmp ++;
            }
            if(sa[i] >= len && sa[i] < n - 1) ret += tmp;
        }
        return ret;
    }
} sol;

void solve()
{
    int len1 = strlen(ch1), len2 = strlen(ch2);
    LL ans = 1ll * len1 * len2;
    ch1[len1 ++] = '#';
    for(int i = 0; i < len2; i ++)
    {
        ch1[len1 ++] = ch2[i];
    }
    ch1[len1] = 0;
    sol.call_fun(ch1);
    ans -= sol.solve(len1 - len2);
    printf("%I64d\n", ans);
}

map<string, int> mp;

void baoli()
{
    mp.clear();
    int len1 = strlen(ch1), len2 = strlen(ch2);
    string tmp = "";
    for(int i = 0; i < len1; i ++)
    {
        tmp += ch1[i];
        string tmp2 = "";
        for(int j = len2 - 1; j >= 0; j --)
        {
            tmp2 += ch2[j];
            reverse(tmp2.begin(), tmp2.end());
            mp[tmp + tmp2] ++;
            reverse(tmp2.begin(), tmp2.end());
        }
    }
    printf("%d -- \n", mp.size());
}
/**
hsdoisdfao
sdfjisdfjiosdfji

hsdo
sdfj
*/
int main()
{
    freopen("concatenation.in", "r", stdin);
    freopen("concatenation.out", "w", stdout);
    while(scanf("%s%s", ch1, ch2) != EOF)
    {
//        baoli();
        solve();
    }
    return 0;
}

D- Distribution in Metagonia

不知道题意。

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define xx first
#define yy second
#define LL unsigned long long
#define MP make_pair
#define INF 0x3f3f3f3f
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))

using namespace std;


int main ()
{
    int t;
    freopen("distribution.in", "r", stdin);
    freopen("distribution.out", "w", stdout);
    cin >> t;
    while(t --)
    {
        LL n;
        cin >> n;
        vector<LL> ans;
        while(n)
        {
            int cnt = 0;
            for(LL now = 2; ; now *= 2)
            {
                if(n % now) break;
                cnt ++;
            }
            LL tmp = 1ll << cnt;
            for(;;)
            {
                if(tmp * 3 <= n)
                {
                    tmp *= 3;
                }
                else
                {
                    break;
                }
            }
            ans.push_back(tmp);
            n -= tmp;
        }
        printf("%d\n", ans.size());
        LL o = 0;
        for(int i = 0; i < ans.size(); i ++)
        {
            printf("%I64u ", ans[i]);
            o += ans[i];
        }
        puts("");
    }
    return 0;
}


E- Easy Arithmetic

简单题。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define xx first
#define yy second
#define LL long long
#define MP make_pair
#define INF 0x3f3f3f3f
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))

using namespace std;

char s[1024];
char num[1024];

int main(){
    freopen("easy.in","r",stdin);
    freopen("easy.out","w",stdout);
    while(scanf("%s",s)!=EOF){
        int n=strlen(s);
        for(int i=0;i<n;i++){
            if(s[i]=='+'){
                putchar(s[i]);
                int j;
                for(j=i+1;j<n&&s[j]<='9'&&s[j]>='0';j++) putchar(s[j]);
                i=j-1;
            }else if(s[i]=='-'){
                putchar(s[i]);
                int l=0,j;
                memset(num,0,sizeof(num));
                for(j=i+1;j<n&&s[j]<='9'&&s[j]>='0';j++) num[l++]=s[j];
                i=j-1;
                int st = l;
                putchar(num[0]);
                for(int j=1;j<l;j++){
                    if(num[j]=='0') printf("+%c",num[j]);
                    else{
                        putchar('+');st=j;break;
                    }
                }
                for(int j=st;j<l;j++) putchar(num[j]);
            }else putchar(s[i]);
        }
        puts("");
        memset(s,0,sizeof(s));
    }
}

G- Graph

题意是要最多+k条边使得字典序最小的拓扑序最大。

首先,对于当前度为0的点个数为sz,如果k>sz-1的话,是可以把最大那个点作为当前拓扑位置的,然后把比较小的那些非配一个未连入的度。否则如果存在未分配度的点u,大于当前度为0的点的话。可以把u放到当前拓扑序的位置(注意加边)。然后当k不够的时候,肯定需要把度为0的那些点中最小的k个分配一个未连入度。然后当k=0时,把有未连入度的点尽量往后放就好了。

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<unordered_map>
#define xx first
#define yy second
#define LL unsigned long long
#define MP make_pair
#define INF 0x3f3f3f3f
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))

using namespace std;

const int maxn = 200000;

vector <int> v[maxn];
int in[maxn];

priority_queue<int> q, q2;
vector<pair<int, int> > ans;

int main ()
{
    freopen("graph.in", "r", stdin);
    freopen("graph.out", "w", stdout);
    int n, m, k;
    while(scanf("%d%d%d", &n, &m, &k) != EOF)
    {
        CLR(in, 0);
        for(int i = 0; i <= n; i ++)
        {
            v[i].clear();
        }
        ans.clear();
        for(int i = 0; i < m; i ++)
        {
            int a, b;
            scanf("%d%d", &a, &b);
            in[b] ++;
            v[a].push_back(b);
        }
        while(!q.empty()) q.pop();
        for(int i = 1; i <= n; i ++)
        {
            if(in[i] == 0) q.push(i);
        }
        while(!q2.empty()) q2.pop();
        int pre = 0;
        while(true)
        {
            if(k == 0)
            {
                while(q.empty())
                {
                    if(q2.empty()) break;
                    int now = q2.top();
                    q2.pop();
                    ans.push_back(MP(pre, now));
                    pre = now;
                    for(int i = 0; i < v[now].size(); i ++)
                    {
                        int to = v[now][i];
                        if(-- in[to] == 0)
                        {
                            q.push(- to);
                        }
                    }
                }
                if(q.empty()) break;
                while(!q.empty())
                {
                    int now = -q.top(); q.pop();
                    pre = now;
                    for(int i = 0; i < v[now].size(); i ++)
                    {
                        int to = v[now][i];
                        if(-- in[to] == 0)
                        {
                            q.push(- to);
                        }
                    }
                }
                continue;
            }
            while(q.empty())
            {
                if(q2.empty()) break;
                int now = q2.top();
                q2.pop();
                ans.push_back(MP(pre, now));
                pre = now;
                for(int i = 0; i < v[now].size(); i ++)
                {
                    int to = v[now][i];
                    if(-- in[to] == 0)
                    {
                        q.push(to);
                    }
                }
            }
            if(q.empty()) break;
            if(!q2.empty() && q.top() < q2.top())
            {
                if(k <= q.size())
                {
                    vector<int> tmp;
                    while(!q.empty()) tmp.push_back(q.top()), q.pop();
                    sort(tmp.begin(), tmp.end());
                    for(int i = 0; i < k; i ++)
                    {
                        q2.push(tmp[i]);
                    }
                    for(int i = k; i < tmp.size(); i ++)
                    {
                        q.push(-tmp[i]);
                    }
                    k = 0;
                    continue;
                }
                int now = q2.top();
                q2.pop();
                ans.push_back(MP(pre, now));
                pre = now;
                k -= q.size();
                while(!q.empty())
                {
                    q2.push(q.top());
                    q.pop();
                }
                for(int i = 0; i < v[now].size(); i ++)
                {
                    int to = v[now][i];
                    if(-- in[to] == 0)
                    {
                        q.push(to);
                    }
                }
                continue;
            }
            if(k <= q.size() - 1)
            {
                vector<int> tmp;
                while(!q.empty()) tmp.push_back(q.top()), q.pop();
                sort(tmp.begin(), tmp.end());
                for(int i = 0; i < k; i ++)
                {
                    q2.push(tmp[i]);
                }
                for(int i = k; i < tmp.size(); i ++)
                {
                    q.push(-tmp[i]);
                }
                k = 0;
                continue;
            }
            k -= q.size() - 1;
            int now = q.top();
            q.pop();
            pre = now;
            while(!q.empty())
            {
                int tmp = q.top();
                q.pop();
                q2.push(tmp);
            }
            for(int i = 0; i < v[now].size(); i ++)
            {
                int to = v[now][i];
                if(-- in[to] == 0)
                {
                    q.push(to);
                }
            }
        }
        for(int i = 0; i < ans.size(); i ++)
        {
            v[ans[i].xx].push_back(ans[i].yy);
        }
        while(!q.empty()) q.pop();
        CLR(in, 0);
        for(int i = 1; i <= n; i ++)
        {
            for(int j = 0; j < v[i].size(); j ++)
            {
                int a = i, b = v[i][j];
                in[b] ++;
            }
        }
        for(int i = 1; i <= n; i ++)
        {
            if(in[i] == 0) q.push(-i);
        }
        vector<int> out;
        while(!q.empty())
        {
            int now = q.top();
            now = -now;
            out.push_back(now);
            q.pop();
            for(int i = 0; i < v[now].size(); i ++)
            {
                int to = v[now][i];
                if(-- in[to] == 0)
                {
                    q.push(-to);
                }
            }
        }
        for(int i = 0; i < out.size(); i ++)
        {
            printf("%d ", out[i]);
        }puts("");
        printf("%d\n", ans.size());
        for(int i = 0; i < ans.size(); i ++)
        {
            printf("%d %d\n", ans[i].xx, ans[i].yy);
        }
    }
    return 0;
}
/**
4 1 1
3 4
*/

H- Hash Code Hacker

水题。题目给了4个相等的,所以随便组合1000个出来就好了。

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define xx first
#define yy second
#define LL long long
#define MP make_pair
#define INF 0x3f3f3f3f
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))

using namespace std;

vector<string> vec;

string st[3] = {"edHs", "fEHs", "edIT"};

void dfs(int i, string tmp)
{
    if(i == 7)
    {
        vec.push_back(tmp);
        return ;
    }
    for(int j = 0; j < 3; j ++)
        dfs(i + 1, tmp + st[j]);
}

void init()
{
    vec.clear();
    dfs(0, "");
}

int main()
{
    freopen("hash.in","r",stdin);
    freopen("hash.out","w",stdout);
    init();
//    printf("%d --\n", vec.size());
    int k;
    while(scanf("%d", &k) != EOF)
    {
        for(int i = 0; i < k; i ++)
            cout << vec[i] << endl;
    }
    return 0;
}

J- Journey to the "The World's Start"

二分花费。然后验证答案。验证的时候用线段树加速一下就好了。

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define xx first
#define yy second
#define LL long long
#define MP make_pair
#define INF 0x3f3f3f3f
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))

using namespace std;

const int maxn = 100100;

int mn[maxn << 2];

void up(int rt)
{
    mn[rt] = min(mn[rt << 1], mn[rt << 1 | 1]);
}

void build(int l, int r, int rt)
{
    if(l == r)
    {
        mn[rt] = INF;
        return ;
    }
    int m = (l + r) >> 1;
    build(lson);
    build(rson);
    up(rt);
}

void update(int p, int v, int l, int r, int rt)
{
    if(l == r)
    {
        mn[rt] = v;
        return ;
    }
    int m = (l + r) >> 1;
    if(p <= m) update(p, v, lson);
    else update(p, v, rson);
    up(rt);
}

int query(int L, int R, int l, int r, int rt)
{
    if(L <= l && r <= R)
    {
        return mn[rt];
    }
    int m = (l + r) >> 1;
    int ret = INF;
    if(L <= m) ret = min(ret, query(L, R, lson));
    if(R > m) ret = min(ret, query(L, R, rson));
    return ret;
}

int p[maxn], d[maxn];
int n, t;

bool check(int pp)
{
    int r = 0;
    for(int i = 1; i < n; i ++)
    {
        if(p[i] <= pp) r = i;
    }
    if(r == 0) return false;
    build(1, n, 1);
    update(1, 0, 1, n, 1);
    for(int i = 2; i <= n; i ++)
    {
        int v = query(max(1, i - r), i - 1, 1, n, 1);
        update(i, v + d[i], 1, n, 1);
    }
    return query(n, n, 1, n, 1) <= t;
}

void solve()
{
    int l = 1, r = p[n - 1];
    while(l <= r)
    {
        int mid = (l + r) >> 1;
        if(check(mid)) r = mid - 1;
        else l = mid + 1;
    }
    printf("%d\n", l);
}

int main()
{
    freopen("journey.in", "r", stdin);
    freopen("journey.out", "w", stdout);
    while(scanf("%d%d", &n, &t) != EOF)
    {
        t -= n - 1;
        for(int i = 1; i < n; i ++)
            scanf("%d", &p[i]);
        for(int i = 2; i < n; i ++)
            scanf("%d", &d[i]);
        d[n] = 0;
        solve();
    }
    return 0;
}

L- Lucky Chances

水题。

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<time.h>
#include<map>
#define xx first
#define yy second
#define LL long long
#define MP make_pair
#define INF 0x3f3f3f3f
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
#define CLR(a, b) memset(a, b, sizeof(a))

using namespace std;

int s[1000][1000];
int main() {
    freopen("lucky.in", "r", stdin);
    freopen("lucky.out", "w", stdout);
    int n, m;
    while(cin >> n >> m) {
        for(int i = 0; i < n; i ++) {
            for(int j = 0; j < m; j ++) {
                scanf("%d", &s[i][j]);
            }
        }
        int ans = 0;
        for(int i = 0; i < n; i ++) {
            for(int j = 0; j < m; j ++) {
                int a = i - 1;
                bool ok = true;
                while(a >= 0) {
                    if(s[a][j] >= s[i][j]) ok = false;
                    a --;
                }
                if(ok) ans ++;

                a = i + 1;
                ok = true;
                while(a < n) {
                    if(s[a][j] >= s[i][j]) ok = false;
                    a ++;
                }
                if(ok) ans ++;

                a = j - 1;
                ok = true;
                while(a >= 0) {
                    if(s[i][a] >= s[i][j]) ok = false;
                    a --;
                }
                if(ok) ans ++;

                a = j + 1;
                ok = true;
                while(a < m) {
                    if(s[i][a] >= s[i][j]) ok = false;
                    a ++;
                }
                if(ok) ans ++;
            }
        }
        cout << ans << endl;
    }
    return 0;
}



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值