CF1719C Fighting Tournament
题意简述:
有 $n$ 个角斗士站在一排 , 士兵的力量值使用一个排列 , 每次对排头前 $2$ 名士兵的力量值进行对比 , 大的人继续站在排头(赢) , 小的人去末尾(输) .
每次给定一个询问 , 给出 $p , k$,表示第 $p$ 位士兵在前 $k$场战斗中赢的次数.
分析:
显然的通过读题(模拟),可以发现在经过最多 $n$ 轮战斗,战斗值最高的士兵会一直站在排头,剩下的士兵会按原顺序排列 (即所有决斗都是排头获胜).
然后就可以暴力模拟 , 通过双端队列和动态数组存储.
代码:
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<vector> #include<set> #include<stack> #include<map> #include<queue> #include<cstdlib> #include<iomanip> #include<utility> #define mid (l+r>>1) #define endl '\n' using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> pai; const double eps = 1e-10; const int base = 13331; const long long mod = 998242353; long long maxn = -2147483647-1,minn = 0x7f7f7f7f; ll a[100005],t,n,m,op,k,player1,player2,ans; vector<ll> v[100005]; int main(){ //freopen("filename.in","r",stdin); //freopen("filename.out","w",stdout); ios::sync_with_stdio(false); cin.tie(0),cout.tie(0); cin>>t; while(t--){ cin>>n>>m; deque<ll> q; for(int i=1;i<=n;++i){ cin>>a[i]; q.push_back(i); v[i].clear(); } for(int i=1;i<=n;++i){ //模拟 player1 = q.front(),q.pop_front(); player2 = q.front(),q.pop_front(); if(a[player1]<a[player2]){ swap(player1,player2); } q.push_front(player1),q.push_back(player2); v[player1].push_back(i); } for(int i=1;i<=m;++i){ ans = 0; cin>>op>>k; ans = upper_bound(v[op].begin(),v[op].end(),k)-v[op].begin(); if(a[op]==n){ ans+=max((ll)0,k-n); } cout<<ans<<endl; } } //fclose(stdin); //fclose(stdout); return 0; }
总结:
有一定细节 , 考场上罚了5发 , 关键是找出最大值在经过 $n$ 轮后永远在排头.

浙公网安备 33010602011771号