P7568 「MCOI-05」追杀
首先这题比较重要的一点是要往暴力去想,因为我们发现
我们先考虑一个比较暴力的做法,暴力枚举对于每个点
我们考虑怎么优化,对于某一个
这么做看起来貌似没有优化做法,但我们发现对于所有以
我们发现对于每一个点
我们发现枚举
最终复杂度
解释起来可能不是很清楚,下面给一下代码
#include <bits/stdc++.h>
// #pragma GCC optimize(2)
#define pcn putchar('\n')
#define ll long long
#define MP make_pair
#define fi first
#define se second
#define gsize(x) ((int)(x).size())
#define Min(a, b) (a = min(a, b))
#define Max(a, b) (a = max(a, b))
#define For(i, j, k) for(int i = (j), END##i = (k); i <= END##i; ++ i)
#define For__(i, j, k) for(int i = (j), END##i = (k); i >= END##i; -- i)
#define Fore(i, j, k) for(int i = (j); i; i = (k))
//#define random(l, r) ((ll)(rnd() % (r - l + 1)) + l)
using namespace std;
namespace IO {
template <typename T> T read(T &num){
num = 0; T f = 1; char c = ' '; while(c < 48 || c > 57) if((c = getchar()) == '-') f = -1;
while(c >= 48 && c <= 57) num = (num << 1) + (num << 3) + (c ^ 48), c = getchar();
return num *= f;
}
template <typename T> void Write(T x){
if(x < 0) putchar('-'), x = -x; if(x == 0){putchar('0'); return ;}
if(x > 9) Write(x / 10); putchar('0' + x % 10); return ;
}
void putc(string s){ int len = s.size() - 1; For(i, 0, len) putchar(s[ i ]); }
template <typename T> void write(T x, string s = "\0"){ Write( x ), putc( s ); }
}
using namespace IO;
/* ====================================== */
const int maxn = 6e4 + 50;
const int maxm = 1e3 + 50;
int n, m;
pair<int, int> a[ maxn ];
int he[ maxn ];
int lst[ maxn ], rge[ maxn ];
int ans[ maxn ];
inline void solve(int ct){ //计算如果强制让ct这个操作失效,最终的答案
For(i, 1, m) he[ i ] = 3;
For(i, 1, n){
if(i == ct){
he[ a[ i ].fi ] = 0; // 这里一定要注意,因为我们钦定ct这个操作失效,因此我们要把x的血量改为0,这样我们只用确定第一个失效的操作,就可以求出对后面的影响
continue;
}
if(!he[ a[ i ].fi ] || !he[ a[ i ].se ]) continue;
-- he[ a[ i ].se ];
}
}
void mian(){
read(n), read(m);
For(i, 1, n) read(a[ i ].fi), read(a[ i ].se);
For(i, 1, m) he[ i ] = 3;
For(i, 1, n){
if(!he[ a[ i ].fi ] || !he[ a[ i ].se ]) continue;
if(he[ a[ i ].fi ] == 1){
rge[ i ] = i - lst[ a[ i ].fi ];
lst[ a[ i ].fi ] = i;
}
-- he[ a[ i ].se ];
}// 先考虑如果XD不击杀任何人,最后存活的人的数量
int lve = 0;
For(i, 1, m) if(he[ i ] > 0) ++ lve; // 存活人的数量
For(i, 1, m){
if(he[ i ] == 1) ans[ lve - 1 ] += n - lst[ i ] + 1; // 考虑XD如果在i这个人1滴血,并且把所有要击杀的玩家都击杀后,XD把他击杀的方案数
if(he[ i ] > 1) ans[ lve ] += n + 1;
if(!he[ i ]) ans[ lve ] += n - lst[ i ] + 1; // 考虑XD如果进行了一次无用的击杀(击杀了超过1滴血的人 或 击杀了已经死亡的人)的方案数
}
For(i, 1, n){
if(!rge[ i ]) continue; // 这里外层循环是O(m)的,因为每个人最多被有效击杀3m次
solve(i);
lve = 0;
For(j, 1, m) if(he[ j ] > 0) ++ lve;
ans[ lve ] += rge[ i ]; // 统计i的方案数
}
For(i, 0, m) write(ans[ i ], " ");
}
void init(){
}
int main() {
#ifdef ONLINE_JUDGE
#else
freopen("data.in", "r", stdin);
// freopen("data.out", "w", stdout);
#endif
int T = 1;
// read(T);
while(T --){
init();
mian();
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?