2013 icpc 杭州 (5.23)

A - Lights Against Dudely

题目链接https://vjudge.net/contest/231392#problem/A

题解

暴力枚举所有的方法,然后去check,更新答案;

代码

//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define lson l,mid,o<<1
#define rson mid+1,r,o<<1|1
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int, int> P;
typedef pair<int, P> PII;
const LL INF = 0x3f3f3f3f;
const int N = 1e5 + 10;
const LL mod = 1e9 + 7;
const double PI=acos(-1);
inline int ab(int x){return x < 0 ? -x : x;}
inline int mm(int x, int p){return x >= p ? x - p : x < 0 ? x + p : x;}


char mp[210][210];
bool vis[210][210];
P node[20];
P now[20];
bool change(int id, int x, int y){
    if(id == 0){
        if(mp[x - 1][y] == '#' || mp[x][y + 1] == '#')  return false;
        vis[x - 1][y] = vis[x][y + 1] = true;
    }
    else if(id == 1){
        if(mp[x - 1][y] == '#' || mp[x][y - 1] == '#')  return false;
        vis[x - 1][y] = vis[x][y - 1] = true;
    }
    else if(id == 2){
        if(mp[x][y - 1] == '#' || mp[x + 1][y] == '#')  return false;
        vis[x][y - 1] = vis[x + 1][y] = true;
    }
    else if(id == 3){
        if(mp[x][y + 1] == '#' || mp[x + 1][y] == '#')  return false;
        vis[x][y + 1] = vis[x + 1][y] = true;
    }
    vis[x][y] = true;
    return true;
}
int main()
{
    int n, m;
    while(scanf("%d%d", &n, &m)){
        if(!n && !m)    break;
        for(int i = 1; i <= n; ++i) scanf("%s", mp[i] + 1);
        for(int i = 0; i <= m + 1; ++i) mp[0][i] = mp[n + 1][i] = '.';
        for(int i = 1; i <= n; ++i) mp[i][0] = mp[i][m + 1] = '.';
        int cnt = 0, tot = 0;
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= m; ++j)
                if(mp[i][j] == '.')
                    node[cnt++] = {i, j};
        if(!cnt){
            printf("0\n");
            continue;
        }
        int ans = INF;
        bool flag = true;
        for(int i = 0; i < cnt; ++i)    vis[node[i].fi][node[i].se] = false;
        for(int i = 0; i < (1 << cnt); ++i){
            tot = 0;
            for(int j = 0; j < cnt; ++j)    if(i & (1 << j))    now[tot++] = node[j];
            for(int j = 0; j < tot; ++j){
                for(int h = 0; h < 4; ++h){
                    if(!change(h, now[j].fi, now[j].se))    continue;
                    flag = true;
                    for(int z = 0; z < tot; ++z){
                        if(z == j) continue;
                        if(!change(0, now[z].fi, now[z].se))  flag = false;
                    }
                    if(flag)
                        for(int z = 0; z < cnt; ++z)    if(!vis[node[z].fi][node[z].se])    flag = false;
                    if(flag)    ans = min(ans, tot);
                    for(int z = 0; z < cnt; ++z)    vis[node[z].fi][node[z].se] = false;
                }
            }
        }
        if(ans == INF)  printf("-1\n");
        else printf("%d\n", ans);
    }
    return 0;
}

B - Stealing Harry Potter’s Precious

题目链接https://vjudge.net/contest/231392#problem/B

C - Zhuge Liang’s Password

题目链接https://vjudge.net/contest/231392#problem/C

D - Problem of Apollonius

题目链接https://vjudge.net/contest/231392#problem/D

E - Random Number Generator

题目链接https://vjudge.net/contest/231392#problem/E

F - Infinite Go

题目链接https://vjudge.net/contest/231392#problem/F

G - Ants

题目链接https://vjudge.net/contest/231392#problem/G

题解

首先可以求出每一位置作为起点的最小的代价并加入到一个集合中,那么这个集合中的最小值一定是所有点对的最小值,假设u出发得到了最小值,那么先将这个最小值删除然后将这个点出发的第次小值加入到队列,然后就一直这样操作下去就可以了

代码

//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define lson l,mid,o<<1
#define rson mid+1,r,o<<1|1
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int, LL> P;
typedef pair<LL, int> PI;
const LL INF = 0x3f3f3f3f;
const int N = 1e5 + 10;
const int M = 62;
const int NM = N * M;
const LL mod = 1e9 + 7;
const double Pi=acos(-1);
inline int ab(int x){return x < 0 ? -x : x;}
inline int mm(int x, int p){return x >= p ? x - p : x < 0 ? x + p : x;}


vector<P>son[N];
LL v[N];
LL ans[N << 1];
int cnt[N];
priority_queue<PI>que;
void dfs(int o, int fa){
    for(auto it : son[o])   if(it.fi != fa)    v[it.fi] = v[o] ^ it.se , dfs(it.fi, o);
}
int node[NM], tot, root, net[NM][2];
int new_node(){
    ++tot;
    node[tot] = net[tot][0] = net[tot][1] = 0;
    return tot;
}
void add(LL x){
    int now = root, u;
    for(int i = 60; i >= 0; --i){
        u = x >> i & 1;
        if(!net[now][u])    net[now][u] = new_node();
        now = net[now][u];
        node[now]++;
    }
}
LL query(LL x, int k){
    int now = root, u;
    LL ret = 0;
    for(int i = 60; i >= 0; --i){
        u = x >> i & 1;
        if(node[net[now][!u]] > k)  now = net[now][!u], ret |= (1ll << i);
        else    k -= node[net[now][!u]], now = net[now][u];
    }
    return ret;
}
int main()
{
    int n;
    while(scanf("%d", &n)){
        if(!n)  break;
        int u, vv;
        LL w;
        for(int i = 1; i <= n; ++i) son[i].clear();
        for(int i = 1; i < n; ++i){
            scanf("%d%d%lld", &u, &vv, &w);
            son[u].push_back({vv, w});
            son[vv].push_back({u, w});
        }
        v[1] = 0, dfs(1, 1);
        tot = 0;    root = new_node();
        for(int i = 1; i <= n; ++i) add(v[i]);
        while(!que.empty()) que.pop();
        for(int i = 1; i <= n; ++i) cnt[i] = 0, que.push({query(v[i], cnt[i]), i});
        PI now;
        int en = min(n * 1ll * (n - 1), 200000ll);
        for(int i = 1; i <= en; ++i){
            now = que.top();    que.pop();
            ans[i] = now.fi;
            cnt[now.se]++;
            if(cnt[now.se] < n - 1) que.push({query(v[now.se], cnt[now.se]), now.se});
        }
        int m;
        scanf("%d", &m);
        for(int i = 1; i <= m; ++i){
            scanf("%d", &u);
            if(u <= en) printf("%lld\n", ans[u]);
            else    puts("-1");
        }
    }
    return 0;
}

H - Rabbit Kingdom

题目链接https://vjudge.net/contest/231392#problem/H

题解

首先可以预处理出来每一个数的互质范围,然后将询问按l排序,那么对于一个询问L, R
我们把所有 位置大于等于L,并且互质范围的左端点小于L的点 在其位置x处加1, 右端点处减1
这样只要统计L-R的区间和就可以了

代码

//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define lson l,mid,o<<1
#define rson mid+1,r,o<<1|1
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int, int> P;
typedef pair<int, P> PII;
const LL INF = 0x3f3f3f3f;
const int N = 2e5 + 10;
const LL mod = 1e9 + 7;
const double PI=acos(-1);
inline int ab(int x){return x < 0 ? -x : x;}
inline int mm(int x, int p){return x >= p ? x - p : x < 0 ? x + p : x;}


bool check[N];
vector<int>vc[N];
void init()
{
    memset(check, false, sizeof(check));
    for(int i = 2; i < N; ++i){
        if(check[i])    continue;
        for(int j = i; j < N; j += i)
            vc[j].push_back(i), check[j] = true;
    }
}
int per[N];
int l[N], r[N];
int v[N];
int n, m;
vector<int>que[N];
vector<P>qer[N];
int ans[N];
int node[N];
int sum(int x){
    int ret = 0;
    for(; x; x -= ( x & (-x)))  ret += node[x];
    return ret;
}
void update(int x, int n, int d){
    for(; x <= n; x += (x & (-x)))  node[x] += d;
}
int main()
{
    init();
    while(scanf("%d%d", &n, &m)){
        if(!n && !m)    break;
        for(int i = 1; i <= n; ++i) scanf("%d", &v[i]);
        for(int i = 0; i <= n; ++i) que[i].clear(), qer[i].clear();
        memset(per, 0, sizeof per);
        for(int i = 1; i <= n; ++i){
            l[i] = 0;
            for(auto it : vc[v[i]])
                l[i] = max(l[i], per[it]), per[it] = i;
            que[l[i]].push_back(i);
        }
        memset(per, INF, sizeof per), r[0] = INF;
        for(int i = n; i >= 1; --i){
            r[i] = INF;
            for(auto it : vc[v[i]])
                r[i] = min(r[i], per[it]),  per[it] = i;
        }
        int ll, rr;
        for(int i = 1; i <= m; ++i){
            scanf("%d%d", &ll, &rr);
            qer[ll].push_back({rr, i});
        }
        memset(node, 0, sizeof node);
        for(int i = 1; i <= n; ++i){
            for(auto it : que[i - 1]){
                update(it, n, 1);
                if(r[it] <= n)   update(r[it], n, -1);
            }
            if(r[i - 1] <= n)   update(r[i - 1], n, 1);
            for(auto it : qer[i])
                ans[it.se] = sum(it.fi) - sum(i - 1);
        }
        for(int i = 1; i <= m; ++i) printf("%d\n", ans[i]);
    }
    return 0;
}

I - Gems Fight!

题目链接https://vjudge.net/contest/231392#problem/I

题解

这一题就是一个状压的爆搜,然后每一个状态表示当前达到这个状态的人的说能获得的最大值,这样就可以只开一维了,开两维会tle

代码

//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define lson l,mid,o<<1
#define rson mid+1,r,o<<1|1
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int, int> P;
typedef pair<int, P> PII;
const LL INF = 0x3f3f3f3f;
const int N = 1e5 + 10;
const LL mod = 1e9 + 7;
const double PI=acos(-1);
inline int ab(int x){return x < 0 ? -x : x;}
inline int mm(int x, int p){return x >= p ? x - p : x < 0 ? x + p : x;}


int dp[1 << 21];
int num[1 << 21];
int cnt[30][10];
int en, n, s, m;
void dfs(int tmp){
    int to, add;
    for(int i = 0; i < n; ++i){
        if(tmp & (1 << i))  continue;
        to = tmp | (1 << i), add = num[to] - num[tmp];
        if(dp[to] == -INF)    dfs(to);
        if(add) dp[tmp] = max(dp[tmp], dp[to] + add);
        else    dp[tmp] = max(dp[tmp], -dp[to]);
    }
}
int main()
{
    while(scanf("%d%d%d", &m, &n, &s)){
        if(!n && !m && !s)    break;
        for(int i = 0; i < (1 << n); ++i)   dp[i] = -INF;
        en = (1 << n) - 1;
        int k, x;
        memset(cnt, 0, sizeof cnt);
        for(int i = 0; i < n; ++i){
            scanf("%d", &k);
            while(k--){
                scanf("%d", &x);
                cnt[i][x]++;
            }
        }
        memset(num, 0, sizeof num);
        int tot[10];
        for(int i = 1; i < (1 << n); ++i){
            memset(tot, 0, sizeof tot);
            for(int j = 0; j < n; ++j){
                if((i >> j) & 1){
                    for(int h = 1; h <= m; ++h){
                        tot[h] += cnt[j][h];
                        while(tot[h] >= s){
                            tot[h] -= s;
                            num[i]++;
                        }
                    }
                }
            }
        }
        dp[en] = 0;
        dfs(0);
        printf("%d\n", dp[0]);
    }
    return 0;
}

J - Tower Defense

题目链接https://vjudge.net/contest/231392#problem/J

K - Candy Factory

题目链接https://vjudge.net/contest/231392#problem/K

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值