1012 Buy Figurines
题意:有n个人到一家商店办事,排m条队,给出ai和si表示第i 个人到达的时间和办事需要的时间,求最后一个人离开窗口的时间。每个人到达窗口的时间都不同,而且每个人都会选择排队人数最少且编号最小的窗口来排队。
思路:对于这n个人,每个人都有一个到达和离开的时间,在时间轴上形成2 ∗ n 个点,可以先将n个人的到达时间放进一个优先队列里,按照时间顺序弹出来,对于弹出来的人,只需要快速的找到这个人放在哪个队列即可,用线段树来维护,再把这个人标记一下再次入堆,等到下一次弹出来的时候修改线段树即可。
#include<bits/stdc++.h>
#define x first
#define y second
#define int long long
using namespace std;
typedef pair<int,int>PII;
const int N=2e5+10,M=3e5+10;
struct person
{
int tm,id,type;
bool operator <(const person &p) const
{
if(tm!=p.tm) return tm>p.tm;
return type>p.type;//先返回在队列中的
}
};
struct Node
{
int l,r;
int cnt,id;
}tr[N*4];
PII p[N];
int pid[N],last[N];
void pushup(int u)
{
tr[u].cnt=min(tr[u<<1].cnt,tr[u<<1|1].cnt);
tr[u].id=tr[u<<1].cnt<=tr[u<<1|1].cnt?tr[u<<1].id:tr[u<<1|1].id;
}
void build(int u,int l,int r)
{
if(l==r) tr[u]={l,r,0,l};
else
{
tr[u]={l,r};
int mid=l+r>>1;
build(u<<1,l,mid);
build(u<<1|1,mid+1,r);
pushup(u);
}
}
void modify(int u,int x,int v)
{
if(tr[u].l==tr[u].r) tr[u].cnt+=v;
else
{
int mid=tr[u].l+tr[u].r>>1;
if(x<=mid) modify(u<<1,x,v);
else modify(u<<1|1,x,v);
pushup(u);
}
}
int query(int u,int l,int r)
{
if(tr[u].l>=l&&tr[u].r<=r) return tr[u].id;
else
{
int mid=tr[u].l+tr[u].r>>1;
if(mid>=r) return query(u<<1,l,r);
else if(l>mid) return query(u<<1|1,l,r);
return min(query(u<<1,l,r),query(u<<1|1,l,r));
}
}
void solve()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++) scanf("%lld %lld",&p[i].x,&p[i].y);
priority_queue<person> heap;
for(int i=1;i<=n;i++)
heap.push({p[i].x,i,1});
for(int i=1;i<=m;i++) last[i]=0;
build(1,1,m);
while(heap.size())
{
auto t=heap.top();
heap.pop();
int type=t.type,id=t.id;
if(type==1)
{
int qid=query(1,1,m);
pid[id]=qid;
last[qid]=max(last[qid],p[id].x)+p[id].y;
modify(1,qid,1);
heap.push({last[qid],id,0});
}
else
{
int qid=pid[id];
modify(1,qid,-1);
}
}
int res=0;
for(int i=1;i<=m;i++) res=max(res,last[i]);
cout<<res<<endl;
}
signed main()
{
int t;
t=1;
cin>>t;
for(int i=1;i<=t;i++)
{
solve();
}
return 0;
}
Problem 1010. Bragging Dice
题意:
两个人玩传统的骰子游戏,现在追加三条规则:1.如果之前没有人叫过1,则1被视为百搭;2.如果手上的骰子点数都相同,则认为有额外的一个相同点数的骰子;3.如果手上的骰子点数互不相同,则认为一个点数也没有。现在双方知道对方的点数,问先手是否必胜。
题解:只要先手能叫,必胜。因此,先手叫不了的情况为必败。
#include<bits/stdc++.h>
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
const int N = 2e5 + 10;
const int mod = 1e9 + 7;
int n, a[N], b[N], c1[8], c2[8];
void solve(){
cin >> n;
for(int i = 1; i <= 6; i++) c1[i] = c2[i] = 0;
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1; i <= n; i++) cin >> b[i];
if(n > 6){
cout << "Win!\n";
return;
}
for(int i = 1; i <= n; i ++){
c1[a[i]] ++, c2[b[i]] ++;
if(c1[a[i]] > 1 || c2[b[i]] > 1){
cout << "Win!\n";
return;
}
}
cout << "Just a game of chance.\n";
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int t = 1;
cin >> t;
while(t--){
solve();
}
}