2021杭电多校第九场题解


two-pointers裸题,每个人单独考虑,记得排序,然后每次一遍双指针,O(n^2)

#include
using namespace std;
const int N=5005;
struct node{int x,id;}a[N];
int n,b[N],ans1[N],ans2[N];
bool cmp(node a,node b){return a.x>b.x;}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1,x;i<=n;i++)scanf("%d",&x),a[i]=(node){x,i};
        sort(a+1,a+n+1,cmp);
        for(int i=1;i<=n;i++)scanf("%d",&b[i]);
        for(int i=1;i<=n;i++)
        {
            int mx=a[i].x+b[1],mn=a[i].x+b[n],cnt1=0,cnt2=0,pos=2;
            for(int j=1;j<=n;j++)
            if(i!=j)
            {
                if(a[j].x+b[n]>mx)++pos,++cnt1;
                else{
                    int p=pos,ret=n-pos+1,num=0;
                    for(int k=n;k>=j;k--)
                    if(i!=k)
                    {
                        while(b[p]+a[k].x>mx)++p;
                        if(p>n)break;
                        ++num,++p;
                    }
                    cnt1+=ret-num;
                    break;
                }
            }
            ans1[a[i].id]=cnt1+1;
            pos=n-1;
            for(int j=1;j<=n;j++)
            if(i!=j)
            {
                if(a[j].x>mn)--pos,++cnt2;
                else{
                    int p=pos;
                    for(int k=j;k<=n;k++)
                    if(i!=k)
                    {
                        if(p<1)break;
                        while(b[p]+a[k].x<=mn)--p;
                        if(p<1)break;
                        ++cnt2,--p;
                    }
                    break;
                }
            }
            ans2[a[i].id]=cnt2+1;
        }
        for(int i=1;i<=n;i++)printf("%d %d\n",ans1[i],ans2[i]);
    }
}

树状数组签到题。

每次询问记录左右端点,然后用树状数组记录当前位置是否存在(存在为1不存在为0)。然后对于询问则采用二分位置+树状数组查询。

可能有同学会好奇为什么不能线段树,这样可以少个log……这很简单,内存是256MB,线段树要开4倍大小,会爆内存

#include
using namespace std;
const int N=2e7+7;
int n,l,r,now,num,c[N],a[N/2],p[N];
void add(int x,int v){while(x<=n)c[x]+=v,x+=x&-x;}
int ask(int x){int ret=0;while(x)ret+=c[x],x-=x&-x;return ret;}
int main()
{
    int q,x;scanf("%d",&q);
    l=q+1,r=q,n=2*q;
    while(q--)
    {
        char c=getchar();
        while(c<'A'||c>'Z')c=getchar();
        if(c=='L')
        {
            ++num,p[--l]=++now,a[now]=l;
            add(l,1);
        }
        else if(c=='R')
        {
            ++num,p[++r]=++now,a[now]=r;
            add(r,1);
        }
        else if(c=='G')scanf("%d",&x),add(a[x],-1),--num;
        else{
            int pos=num/2+1,L=l,R=r,mid,ans=r;
            while(L<=R)
            {
                mid=L+R>>1;
                if(ask(mid)-ask(l-1)>=pos)ans=mid,R=mid-1;
                else L=mid+1;
            }
            printf("%d\n",p[ans]);
        }
    }
}

未完待续……

相关