题解:
按照每个店铺id为第一关键字,时间t为第二关键字升序排序。
把每个店铺看做一个集合label,集合中元素为该店铺的订单时间。(以下叙述均称每一个店铺为集合)
对于每一个集合,按照订单时间先后顺序扫描,扫描过程中记录该店铺的实时状态(是否在缓存中),并记录当前的优先级。
遇到一个新集合时,此时应该判断上一个集合是否满足条件,判断末状态即可,更新答案。
细节:在遇到新集合时,上一个集合的最后一个订单时间可能不是T,那么随着时间流逝,优先级应该随着T减少,此刻应该注意判断。
时间复杂度:$O(M * logM + M)$
C++ 代码
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e5 + 10;
int cnt[N];
struct message
{
int t, id;
bool operator < (const message& m)
{
return id < m.id || id == m.id && t < m.t;
}
}m[N];
int main()
{
int n, M, T;
scanf("%d%d%d", &n, &M, &T);
for(int i = 0; i < M; i++) scanf("%d%d", &m[i].t, &m[i].id);
sort(m, m + M);
int cur = 2, ans = 0;
bool flag = false;
for(int i = 1; i <= M; i++)
{
if(m[i].id != m[i-1].id)
{
if(flag && cur - (T - m[i-1].t) > 3) ans++; //注意判断末订单时间
flag = false; //恢复初始值,为当前集合服务
cur = 2;
}
else
{
int diff = m[i].t - m[i-1].t - 1;
if(diff == -1) diff = 0;
cur = max(0, cur - diff);
if(cur <= 3) flag = false;
cur += 2;
if(cur > 5) flag = true;
}
}
printf("%d\n", ans);
return 0;
}
出来挨打,谢谢
加了注释
可以参考下
思路太好了
草稿纸比划了下,发现代码思路很清晰
出来挨打谢谢
ORZ一直都是考虑给时间排序一个点一个点处理,给ID排序一次处理一家店确实妙
``package com.zeng.acwing;
import java.util.Arrays;
import java.util.Scanner;
class Pair implements Comparable[HTML_REMOVED] {
int ts, id;
public Pair(int ts, int id) {
this.id = id;
this.ts = ts;
}
}
public class Main {
public static int cnt = 0, n, m, T;
public static final int N = 100010;
public static Pair[] g = new Pair[N];
public static int[] p = new int[N];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
T = sc.nextInt();
for (int i = 0; i < m; i++) {
g[i] = new Pair(sc.nextInt(), sc.nextInt());
}
Arrays.sort(g, 0, m);
int prevId = 0, prevTs = 0, sum = 0;
boolean flag = false;
}``
按你这个思路写的,不东为什么有漏几个
好思路
我来打你了
看了几遍终于明白了。还是没好好看,题解,把id一样的看作同一个集合来处理,也就是按照id来一个个的处理
太天真了!你以为这我就懂了?
还有i为啥循环到m呢
还有i为啥循环到m呢
cur为什么初始值是二呢
观察循环是从1到m的 所以m[0]的订单是没有加上的 所以cur初始化为2是加上m[0] 然后后面的每一步都是加上集合中的第一个 所有一直初始化为2