线段树。http://acm.hdu.edu.cn/showproblem.php?pid=4302
求距离离某点距离最短的点的下标。
刚开始初始化的时候没初始对, Orz了好久。还以为有什么问题呢。
#include <cstdio>
#include <iostream>
#define inf 100010
#define maxn 100010
#define ls rt << 1
#define rs rt << 1 | 1
#define lson l, m , rt << 1
#define rson m + 1, r, rt << 1 | 1
#define havem int m = (l + r) >> 1
using namespace std;
int T,n, Q, op, pos, now, dir, ans;
int val[maxn << 2], mmax[maxn << 2], mmin[maxn << 2];
void build(int l, int r, int rt){
val[rt] = 0;
mmax[rt] = -inf;
mmin[rt] = inf;
if(l == r) return ;
havem;
build(lson); build(rson);
}
void update(int pos, int cc, int l,int r, int rt){
if(l == r) {
val[rt] += cc;
if(val[rt]){
mmax[rt] = mmin[rt] = pos;//
}else{
mmax[rt] = -inf;
mmin[rt] = inf;
}
return ;
}havem;
if(pos <= m) update(pos,cc,lson);
else update(pos,cc,rson);
mmax[rt] = max(mmax[ls], mmax[rs]);
mmin[rt] = min(mmin[ls], mmin[rs]);
}
int find_max(int L, int R, int l, int r, int rt){
if(L <= l && r <= R){
return mmax[rt];
}
int ret = -inf; havem;
if(L <= m) ret = find_max(L,R,lson);
if(R > m) ret = max( ret,find_max(L,R,rson) );
return ret;
}
int find_min(int L, int R, int l, int r, int rt){
if(L <= l && r <= R){
return mmin[rt];
}
int ret = inf; havem;
if(L <= m) ret = find_min(L,R,lson);
if(R > m) ret = min( ret,find_min(L,R,rson) );
return ret;
}
int main(){
scanf("%d",&T);
for(int ca = 1; ca <= T; ca ++){
scanf("%d%d",&n, & Q);
build(0,n,1);
now = 0, dir = 1, ans = 0;
for(int i = 0; i < Q; ++ i){
scanf("%d", & op);
if(op == 0){
scanf("%d",&pos);
update(pos, 1, 0, n, 1);
}else{
int l = find_max(0, now, 0, n, 1);
int r = find_min(now, n, 0, n, 1);
if(l <= -inf && r >= inf){
continue;
}else if(l <= -inf){
ans += r - now, now = r, dir = 1;
}else if(r >= inf){
ans += now - l, now = l, dir = 0;
}else if(now - l < r - now){
ans += now - l, now = l, dir = 0;
}else if(now - l > r - now){
ans += r - now, now = r, dir = 1;
}else {
if(dir){
ans += r - now, now = r;
}else{
ans += now - l, now = l;
}
}//printf("%d %d %d kaka\n", l, r, now);
update(now, -1, 0, n, 1);
}
}
printf("Case %d: %d\n", ca, ans);
}
return 0;
}
这题优先队列就可以过, Orz。。。
priority_queue<int> L; //大顶堆
priority_queue<int,vector<int>,greater<int> > R; //小顶堆
int main()
{
int T;
scanf("%d",&T);
for(int cas=1;cas<=T;cas++)
{
while(!L.empty()) L.pop();
while(!R.empty()) R.pop();
int len,n,pos=0,dir=1;
__int64 ans=0;
scanf("%d%d",&len,&n);
for(int i=0;i<n;i++)
{
int flag;
scanf("%d",&flag);
if(!flag)
{
int temp;
scanf("%d",&temp);
if(temp>pos)
R.push(temp);
else
L.push(temp);
}
else
{
int l=-1000000,r=1000000;
if(L.empty() && R.empty()) continue;
if(!L.empty()) l=L.top();
if(!R.empty()) r=R.top();
if(r-pos<pos-l) dir=1;
else if(pos-l<r-pos) dir=0;
if(dir)
{
ans+=r-pos;
pos=r;
R.pop();
}
else
{
ans+=pos-l;
pos=l;
L.pop();
}
}
}
printf("Case %d: %I64d\n",cas,ans);
}
return 0;
}