目录

1010 Bragging Dice

题目

​ 两个人玩明牌的 “吹牛骰子” 游戏,求先手和后手谁赢。 一个人投出的点数全部不同时,视为没有点数。

分析

​ 只有当一个塞子都没有的情况下后手必胜,否则先手必胜

代码

#include<bits/stdc++.h>
using namespace std;

int n;
int a[10],b[10];

int main(){
    //freopen("data.in","r",stdin);
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int T;
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);
		int x;
		memset(a,0,sizeof(a));
		memset(b,0,sizeof(b));
		bool flag1,flag2;
		flag1=flag2=1;
		for(int i=1;i<=n;i++) {
            scanf("%d",&x);
            if(a[x]) flag1=0;
            a[x]++;
		}
		for(int i=1;i<=n;i++) {
            scanf("%d",&x);
            if(b[x]) flag2=0;
            b[x]++;
		}
		if(flag1&&flag2) printf("Just a game of chance.\n");
		else printf("Win!\n");
	}
    return 0;
}

1012 Buy Figurines

题目

​ n个人m个窗口买手办,每个人有对应到的时间和花费的时间,问最后一个人离开的时间。

分析

​ 模拟题。利用两个优先队列,一个维护队列第一个人离开时间,一个维护每个队列的人数。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int INF=0x3f3f3f3f;
const int mod=1e3+7;
const int N=2e5+10,M=5e5+5;

int n,m;
struct node {
    ll t; int id;
    bool operator<(const node &b) const {
        if(t==b.t) return id>b.id;
        return t>b.t;
    }
};

struct person {
    int x,y;
    bool operator<(const person &b) const {
        return x<b.x;
    }
}p[N];

struct seg{
    int x,id;
    bool operator<(const seg &b) const {
        if(x==b.x) return id>b.id;
        return x>b.x;
    }
};

long long te[N]; //每个队第一个离开时间
queue<int> q[N];

int main(){
    // freopen("data.in","r",stdin);
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int T;
    scanf("%d",&T);
    while(T--) {
        memset(te,0,sizeof(te));
        priority_queue<node> heapa;
        priority_queue<seg> heapb;
        scanf("%d%d",&n,&m);
        int x,y;
        for(int i=1;i<=n;i++) {
            scanf("%d%d",&x,&y);
            p[i]={x,y};
        }
        sort(p+1,p+n+1);
        for(int i=1;i<=m;i++) {
            heapb.push({0,i});
        }
        for(int i=1;i<=n;i++) {
            while(heapa.size()) {  // 出队
                int id=heapa.top().id;
                if(te[id]<=p[i].x) {
                    q[id].pop();
                    while(q[id].size()) {
                        if(te[id]+q[id].front()<=p[i].x) {
                            te[id]+=q[id].front();
                            q[id].pop();
                        } else {
                            te[id]+=q[id].front();
                            break;
                        }
                    }
                    heapa.pop();
                    if(q[id].size()) {
                        heapa.push({te[id],id});
                    }
                    heapb.push({q[id].size(),id});
                } else break;
            }

            // 入队
            seg que=heapb.top(); heapb.pop();
            while(q[que.id].size()!=que.x) { // 过时信息
                 que=heapb.top(); heapb.pop();
            }
            int id=que.id;
            //printf("i=%d id=%d\n",i,id);
            if(q[id].size()==0) { // 队伍为空
                te[id]=p[i].x+p[i].y;
                heapa.push({te[id],id});
            }
            q[id].push(p[i].y);
            heapb.push({q[id].size(),id});
        }

        ll ans=0;
        for(int i=1;i<=m;i++) {
            if(q[i].size()) q[i].pop();
            while(q[i].size()) {
                te[i]+=q[i].front();
                q[i].pop();
            }
            ans=max(ans,te[i]);
        }
       printf("%lld\n",ans);
    }
    return 0;
}

1003 Slipper

题目

​ 给定一棵树和树上边权,每次可以走树上的边,也可以花费 p 的代价向上或向下跳 k层。求点 s到点 t 的最短路。

分析

​ 在建立树的基础上,对于相差k层的节点建立权值为p的边,可以给同一层建立公共的节点,减少边的数量。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<long long,int> PII;
const int INF=0x3f3f3f3f;
const int mod=1e3+7;
const int N=4e6+10,M=5e5+5;

int n,k,p,s,t;
int h[N],ver[N],ne[N],e[N],tot=0;
int dep[N],st[N],maxDep=0;
ll dis[N];

void add(int x,int y,int z) {
    ver[++tot]=y; ne[tot]=h[x];
    e[tot]=z; h[x]=tot;
}

void dfs(int x,int fa) {
    dep[x]=dep[fa]+1;
    maxDep=max(maxDep,dep[x]);
    for(int i=h[x];~i;i=ne[i]) {
        int y=ver[i];
        if(y==fa) continue;
        dfs(y,x);
    }
}

void dijkstra() {
    memset(dis,0x3f,sizeof(dis));
    memset(st,0,sizeof(st));
    priority_queue<PII> q;
    dis[s]=0; q.push({0,s});
    while(q.size()) {
        int x=q.top().second; q.pop();
        if(st[x]) continue;
        st[x]=true;
        for(int i=h[x];~i;i=ne[i]) {
            int y=ver[i],z=e[i];
            if(dis[y]>dis[x]+z) {
                dis[y]=dis[x]+z;
                q.push({-dis[y],y});
            }
        }
    }
}

int main() {
    freopen("data.in","r",stdin);
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int T;
    scanf("%d",&T);
    while(T--) {
        tot=0; memset(h,-1,sizeof(h));
        scanf("%d",&n);
        int u,v,w;
        for(int i=2;i<=n;i++) {
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w); add(v,u,w);
        }
        scanf("%d%d",&k,&p);
        scanf("%d%d",&s,&t);
        dep[0]=-1;
        dfs(1,0);
        for (int i = 1; i <= n; ++i) {
            //printf("dep=%d\n",dep[i]);
            if (dep[i] != 0)
                add(n + 2 * dep[i] - 1, i, p);
            if (dep[i] != maxDep)
                add(n + 2 * (dep[i] + 1), i, p);
            if (dep[i] + k <= maxDep)
                add(i, n + 2 * (dep[i] + k) - 1, 0);
            if (dep[i] - k >= 0)
                add(i, n + 2 * (dep[i] - k + 1), 0);
        }
        dijkstra();
        printf("%lld\n",dis[t]);
    }
    return 0;
}