Codeforces Round #296 (Div. 1) A,B题解

最近小四门忙的都没什么时间码代码了...

切掉两题还是掉掉掉啊...

----------------------------------------------------------------------------------------------------------------------------------------------------------------------

A.Glass Carving

给你一个矩形。每次切一刀。问你每切完一刀后所分成的部分中的最大面积





维护长和宽的最大值,然后直接相乘得出ans

维护的时候似乎可以用set或者别的一些东西

当时感觉自己还不太会用结果写了两棵线段树= =写了200多行。导致的结果就是别人出两题我才把这题切了

线段树就是一开始是000000的序列。每次切割相当于把0改成1。求最长的连续0的长度

----------------------------------------------------------------------------------------------------------------------------------------------------------------------

B.Clique Problem

在数轴上有一些点Xi,每个点有一个权值Wi。两点之间若满足丨Xi-Xj丨>=Wi+Wj 则连边。问你最大的两两连边的点的集合大小





首先我们可以发现一个性质,如果X和Y连边,Y和Z连边,那么X和Z必定有边

那么就很容易考虑状态转移了 F[i]=max(F[j])+1

移项后可以发现,把点按照Xi+Wi排序就可以保证与该点有边则与该点左边均有边

把点排序,然后我们二分找到左边第一个可以连边的点k,再用一棵线段树维护1到k中间F[]的最大值直接转移就可以了

【第一题写的线段树这里又用上了】

----------------------------------------------------------------------------------------------------------------------------------------------------------------------

code:

A.Glass Carving

#include<map>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
struct tree
{
     long long l,r;
     long long l0,r0;
     long long s;
}tr1[1600001],tr2[1600001];
inline void up1(int p)
{
     tr1[p].l0=tr1[p*2].l0;
     if(tr1[p*2].l0==tr1[p*2].r-tr1[p*2].l+1)
          tr1[p].l0+=tr1[p*2+1].l0;
     tr1[p].r0=tr1[p*2+1].r0;
     if(tr1[p*2+1].r0==tr1[p*2+1].r-tr1[p*2+1].l+1)
          tr1[p].r0+=tr1[p*2].r0;
     tr1[p].s=max(max(tr1[p*2].r0+tr1[p*2+1].l0,tr1[p*2].s),tr1[p*2+1].s);
}
inline void build1(int p,int l,int r)
{
     tr1[p].l=l;
     tr1[p].r=r;
     if(l!=r)
     {
          int mid=(l+r)/2;
          tr1[p].l=l;
          tr1[p].r=r;
          build1(p*2,l,mid);
          build1(p*2+1,mid+1,r);
          up1(p);
     }
     else
     {
          tr1[p].l0=1;
          tr1[p].r0=1;
          tr1[p].s=1;
     }
}
inline void up2(int p)
{
     tr2[p].l0=tr2[p*2].l0;
     if(tr2[p*2].l0==tr2[p*2].r-tr2[p*2].l+1)
          tr2[p].l0+=tr2[p*2+1].l0;
     tr2[p].r0=tr2[p*2+1].r0;
     if(tr2[p*2+1].r0==tr2[p*2+1].r-tr2[p*2+1].l+1)
          tr2[p].r0+=tr2[p*2].r0;
     tr2[p].s=max(max(tr2[p*2].r0+tr2[p*2+1].l0,tr2[p*2].s),tr2[p*2+1].s);
}
inline void build2(int p,int l,int r)
{
     tr2[p].l=l;
     tr2[p].r=r;
     if(l!=r)
     {
          int mid=(l+r)/2;
          tr2[p].l=l;
          tr2[p].r=r;
          build2(p*2,l,mid);
          build2(p*2+1,mid+1,r);
          up2(p);
     }
     else
     {
          tr2[p].l0=1;
          tr2[p].r0=1;
          tr2[p].s=1;
     }
}
inline void change1(int p,int x)
{
     if(tr1[p].l==x&&tr1[p].r==x)
     {
          tr1[p].l0=0;
          tr1[p].r0=0;
          tr1[p].s=0;
     }
     else
     {
          int mid=(tr1[p].l+tr1[p].r)/2;
          if(x<=mid)
               change1(p*2,x);
          else
               change1(p*2+1,x);
          up1(p);
     }
}
inline void change2(int p,int x)
{
     if(tr2[p].l==x&&tr2[p].r==x)
     {
          tr2[p].l0=0;
          tr2[p].r0=0;
          tr2[p].s=0;
     }
     else
     {
          int mid=(tr2[p].l+tr2[p].r)/2;
          if(x<=mid)
               change2(p*2,x);
          else
               change2(p*2+1,x);
          up2(p);
     }
}
tree xtt;
inline tree ask1(int p,int l,int r)
{
     if(l<=tr1[p].l&&tr1[p].r<=r)
          return tr1[p];
     else
     {
          int mid=(tr1[p].l+tr1[p].r)/2;
          tree ans1=xtt,ans2=xtt,ans=xtt;
          bool flag1=false,flag2=false;
          if(l<=mid)
          {
               flag1=true;
               ans1=ask1(p*2,l,r);
          }
          if(r>mid)
          {
               flag2=true;
               ans2=ask1(p*2+1,l,r);
          }
          if(flag1)
          {
               if(flag2)
               {
                    ans.l0=ans1.l0;
                    if(ans1.l0==ans1.r-ans1.l+1)
                         ans.l0+=ans2.l0;
                    ans.r0=ans2.r0;
                    if(ans2.r0==ans2.r-ans2.l+1)
                         ans.r0+=ans1.r0;
                    ans.s=max(max(ans1.r0+ans2.l0,ans1.s),ans2.s);
                    ans.l=ans1.l;
                    ans.r=ans2.r;
               }
               else
                    ans=ans1;
          }
          else
               ans=ans2;
          return ans;
     }
}
inline tree ask2(int p,int l,int r)
{
     if(l<=tr2[p].l&&tr2[p].r<=r)
          return tr2[p];
     else
     {
          int mid=(tr2[p].l+tr2[p].r)/2;
          tree ans1=xtt,ans2=xtt,ans=xtt;
          bool flag1=false,flag2=false;
          if(l<=mid)
          {
               flag1=true;
               ans1=ask2(p*2,l,r);
          }
          if(r>mid)
          {
               flag2=true;
               ans2=ask2(p*2+1,l,r);
          }
          if(flag1)
          {
               if(flag2)
               {
                    ans.l0=ans1.l0;
                    if(ans1.l0==ans1.r-ans1.l+1)
                         ans.l0+=ans2.l0;
                    ans.r0=ans2.r0;
                    if(ans2.r0==ans2.r-ans2.l+1)
                         ans.r0+=ans1.r0;
                    ans.s=max(max(ans1.r0+ans2.l0,ans1.s),ans2.s);
                    ans.l=ans1.l;
                    ans.r=ans2.r;
               }
               else
                    ans=ans1;
          }
          else
               ans=ans2;
          return ans;
     }
}
int main()
{
     int w,h,n;
     scanf("%d%d%d",&w,&h,&n);
     int i;
     char x[10];
     int xt;
     build1(1,1,h-1);
     build2(1,1,w-1);
     for(i=1;i<=n;i++)
     {
          scanf("%s",x);
          if(x[0]=='H')
          {
               scanf("%d",&xt);
               change1(1,xt);
          }
          else if(x[0]=='V')
          {
               scanf("%d",&xt);
               change2(1,xt);
          }
          printf("%I64d\n",(ask1(1,1,h).s+1)*(ask2(1,1,w).s+1));
     }
     return 0;
}

B. Clique Problem

#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
int f[200001];
struct point
{
     int x,w;
}a[200001];
inline bool cmp(point x,point y)
{
     if(x.x+x.w<y.x+y.w)
          return true;
     else if(x.x+x.w==y.x+y.w)
          if(x.x<y.x)
               return true;
     return false;
}
struct tree
{
     int l,r;
     int s;
}tr[1600001];
inline void build(int p,int l,int r)
{
     tr[p].l=l;
     tr[p].r=r;
     if(l!=r)
     {
          int mid=(l+r)/2;
          build(p*2,l,mid);
          build(p*2+1,mid+1,r);
     }
}
inline void change(int p,int x,int xt)
{
     if(tr[p].l==x&&tr[p].r==x)
          tr[p].s=xt;
     else
     {
          int mid=(tr[p].l+tr[p].r)/2;
          if(x<=mid)
               change(p*2,x,xt);
          else
               change(p*2+1,x,xt);
          tr[p].s=max(tr[p*2].s,tr[p*2+1].s);
     }
}
inline int ask(int p,int l,int r)
{
     if(l<=tr[p].l&&tr[p].r<=r)
          return tr[p].s;
     else
     {
          int mid=(tr[p].l+tr[p].r)/2;
          int ans=0;
          if(l<=mid)
               ans=ask(p*2,l,r);
          if(r>mid)
               ans=max(ask(p*2+1,l,r),ans);
          return ans;
     }
}
int main()
{
     int n;
     scanf("%d",&n);
     int i;
     for(i=1;i<=n;i++)
          scanf("%d%d",&a[i].x,&a[i].w);
     sort(a+1,a+1+n,cmp);
     build(1,1,n);
     f[1]=1;
     change(1,1,f[1]);
     for(i=2;i<=n;i++)
     {
     	  int l=1,r=i-1;
     	  int mid;
     	  while(l<=r)
     	  {
     	  	   mid=(l+r)/2;
     	       if(a[i].x-a[mid].x>=a[i].w+a[mid].w)
     	            l=mid+1;
     	       else
     	            r=mid-1;
     	  }
          f[i]=ask(1,1,r)+1;
          change(1,i,f[i]);
     }
     int ans=0;
     for(i=1;i<=n;i++)
          ans=max(ans,f[i]);
     printf("%d\n",ans);
     return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值