Unfair Tournament
Unfair Tournament
这个也不放题面了。
题解
很容易发现,如果这个人可以成为冠军,那么一定有一种办法是他一个人把全部人都给打掉。
于是我们就得到了一个
O
(
n
2
)
O(n^2)
O(n2)的暴力 ,虽然笔者连这个都打爆了。
很明显,其实没必要对于每个人都让它看看能不能打。
对于最大的人,它一定可以成为冠军。其它人挨着他时打掉他,就可以成为冠军。
相当于他将这个序列分成两段,两段的人是互不干扰的,谁能打掉分水岭,谁就能胜利。
将这个过程往下推,我们就得到了一个类似笛卡尔树的东西。
对于一个点,打掉它的所有祖先就能够获胜。
而当祖先直面某个儿子时,一定有一种最优方法是这个儿子已经打掉了他所在子树的所有点。
所以,这个儿子的权值只要大于他祖先的权值减这个子树除去他的大小即可。
我们可以通过这个方法对每个节点加上若干个限制,而每个节点只要满足最大的一个限制即可。
所以,我们只需要用dfs的方法遍历下去即可。
时间复杂度 O ( n l o g n ) O\left(nlog\,n\right) O(nlogn)。
源码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#include<map>
using namespace std;
#define MAXN 500005
#define lowbit(x) (x&-x)
#define reg register
typedef long long LL;
typedef unsigned long long uLL;
typedef unsigned int uint;
typedef pair<int,int> pii;
const int INF=0x7f7f7f7f;
const int mo=1e9+7;
const double PI=acos(-1.0);
const int jzm=2333;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
_T f=1;x=0;char s=getchar();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
x*=f;
}
int n,a[MAXN],tr[MAXN<<2],sta[MAXN],stak;
void build(int rt,int l,int r){
if(l==r){tr[rt]=l;return ;}int mid=l+r>>1;
build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);
tr[rt]=a[tr[rt<<1]]>a[tr[rt<<1|1]]?tr[rt<<1]:tr[rt<<1|1];
}
int query(int rt,int l,int r,int al,int ar){
if(l>r||l>ar||r<al)return 0;int mid=l+r>>1;
if(al<=l&&r<=ar)return tr[rt];int res=0;
if(al<=mid){int tmp=query(rt<<1,l,mid,al,ar);res=a[res]<a[tmp]?tmp:res;}
if(ar>mid){int tmp=query(rt<<1|1,mid+1,r,al,ar);res=a[res]<a[tmp]?tmp:res;}
return res;
}
void solve(int l,int r,int lim){
if(l>r)return ;int p=query(1,1,n,l,r);if(a[p]>=lim)sta[++stak]=p;
solve(l,p-1,max(lim,a[p]-p+l+1));solve(p+1,r,max(lim,a[p]-r+p+1));
}
signed main(){
read(n);for(int i=1;i<=n;i++)read(a[i]);build(1,1,n);solve(1,n,0);
sort(sta+1,sta+stak+1);printf("%d\n",stak);
for(int i=1;i<=stak;i++)printf("%d ",sta[i]);puts("");
return 0;
}

浙公网安备 33010602011771号