树状数组,1时候,二分左边第一个不是0的位置,和二分右边第一个不是0的位置.
#include<cstdio>
#include<queue>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<string>
#include <iostream>
#include<cmath>
using namespace std;
const int inf=1<<30;
const int M=100030;
int num[M];
int n,q;
int C[M];
int lowbit(int t)
{
return t&(-t);
}
void modify(int p,int x)
{
num[p]+=x;
for(int i=p;i<M;i+=lowbit(i))
C[i]+=x;
}
int getsum(int x)
{
int s=0;
for(int i=x;i>0;i-=lowbit(i))
s+=C[i];
return s;
}
int getleft(int L,int R,int s)//二分左边
{
int mid;
while(L<=R)
{
mid=(L+R)/2;
int tmp = getsum(mid);
if(tmp<s) L=mid+1;
else if(num[mid]==0) R=mid-1;
else return mid;
}
}
int getrihgt(int L,int R,int s)//二分右边
{
int mid;
while(L<R)
{
mid=(L+R)/2;
int tmp = getsum(mid);
if(tmp==s) L=mid+1;
else if(num[mid]==0) R=mid-1;
else R = mid;
}
return L;
}
int main()
{
int ca;
cin>>ca;
int cas;
cas=1;
while(ca--)
{
scanf("%d%d",&n,&q);
int flag=1;//上次移动的方向
int now=1;//当前位置
int ans=0;
memset(num,0,sizeof(num));
memset(C,0,sizeof(C));
int ch;
while(q--)
{
scanf("%d",&ch);
if(ch==0)
{
int pp;
cin>>pp;
pp++;
modify(pp,1);
}
if(ch==1)
{
if(num[now]>0)
{
modify(now,-1);
continue;
}
int p_L=0;
int p_R=0;
int mm=getsum(now);
int m_L=getsum(now-1);
int m_R=getsum(n+1);
if(m_L>0) p_L=getleft(1,now,mm);
if(m_R>mm) p_R=getrihgt(now,n+1,mm);
if((!p_L)&&p_R)
{
ans += p_R-now;
now = p_R;
flag = 1;
modify(now, -1);
}
else if(p_L&&!p_R)
{
ans += now-p_L;
now = p_L;
flag = 0;
modify(now, -1);
}
else if(p_L&&p_R)
{
if(p_R-now==now-p_L)
{
if(flag)
{
ans += p_R-now;
now = p_R;
modify(now,-1);
}
else
{
ans += now-p_L;
now = p_L;
modify(now, -1);
}
}
else if(now-p_L<p_R-now)
{
ans += now-p_L;
now = p_L;
flag = 0;
modify(now, -1);
}
else if(now-p_L > p_R-now)
{
ans += p_R-now;
now = p_R;
flag = 1;
modify(now, -1);
}
}
}
}
printf("Case %d: %d\n",cas++,ans);
}
return 0;
}
多校第一场:hdu(4302)(树状数组+二分)
最新推荐文章于 2019-08-21 20:01:53 发布