洛谷 P5749 [IOI2019]排列鞋子
作者:互联网
竟然是IOI的题目!我惊了!
结论,每只鞋子,找最近的去匹配,就是最优的
证明见木木 !的博客
我们于是有朴素算法
先将鞋子按照左右脚分类,再按值分类
然后从后往前依次配对所有鞋子
首先能配对的鞋子必定在它之前的,所以只用找对应的vector里的最后一只,然后坐标减一减就是贡献,注意左右脚的区别
然后标记两只鞋,表示已经用过,vector则弹出最后的元素(pop_back())
一提交 10pts???
原来有些鞋子匹配好了(由于我们从后往前,匹配好了就是移到最后形成一双),导致剩余鞋子之间的距离减小
我们开一个树状数组统计区间里有多少只鞋子已经不在了
每次计算贡献时减去区间内已经空了的位子数
[Code]
#include <bits/stdc++.h>
using namespace std;
int read(){
int x=0,flag=1; char c;
for(c=getchar();!isdigit(c);c=getchar()) if(c=='-') flag=-1;
for(;isdigit(c);c=getchar()) x=((x+(x<<2))<<1)+(c^48);
return x*flag;
}
const int N=1e5+10;
int n;
vector<int> a[N],b[N];
vector<int>::iterator it;
int g[N+N];
bool use[N+N];
int c[N+N];
int lowbit(int x) { return x&(-x); }
void update(int x,int y){
for(int i=x;i<=n+n;i+=lowbit(i)) c[i]+=y;
}
int query(int x){
int ret=0;
for(int i=x;i>0;i-=lowbit(i)) ret+=c[i]; return ret;
}
int main() {
n=read();
for(int i=1;i<=n+n;i++){
int x=read();
g[i]=x;
if(x>0) a[x].push_back(i);
else b[-x].push_back(i);
}
long long ans=0;
for(int i=n+n;i>=1;i--){
if(use[i]) continue;
if(g[i]>0){
it=b[g[i]].end(); --it;
ans+=i-*it-1-query(i)+query(*it-1);
use[*it]=1;
update(*it,1); update(i,1);
b[g[i]].pop_back();
a[g[i]].pop_back();
}else{
it=a[-g[i]].end(); --it;
ans+=i-*it-query(i)+query(*it-1);
use[*it]=1;
update(*it,1); update(i,1);
a[-g[i]].pop_back();
b[-g[i]].pop_back();
}
}
printf("%lld\n",ans);
return 0;
}
标签:IOI2019,洛谷,P5749,back,pop,update,int,鞋子,query 来源: https://www.cnblogs.com/zzhzzh123/p/12219090.html