最近小四门忙的都没什么时间码代码了...
切掉两题还是掉掉掉啊...
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
给你一个矩形。每次切一刀。问你每切完一刀后所分成的部分中的最大面积
维护长和宽的最大值,然后直接相乘得出ans
维护的时候似乎可以用set或者别的一些东西
当时感觉自己还不太会用结果写了两棵线段树= =写了200多行。导致的结果就是别人出两题我才把这题切了
线段树就是一开始是000000的序列。每次切割相当于把0改成1。求最长的连续0的长度
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
在数轴上有一些点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:
#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;
}