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$ 轮后永远在排头.

posted @ 2022-08-17 14:27  风絮烟雨  阅读(21)  评论(0)    收藏  举报