先把会的写一下题解吧,以后慢慢补上。
HDU 6217-Hard challenge
题意:二维平面内有n个点,每个点都有坐标和一个val值,任意两点之间都有一条线段连接,线段的贡献值为两个端点的val之积,且不存在过两个点的直线也经过原点。求一条过原点的直线与线段相交所得的贡献值最大。应该算简单的计算几何吧。先来看一个不等式:ab<=((a+b)^2)/2 当且仅当a=b时取等。根据题意,我们自然可以用一条直线将这些点划分为两个集合(这样就和过原点的直线相交了),答案即这两个集合的val之积。现在怎么将这些val分成两个集合并且差值最小呢,注意tot_val<=5e8。背包肯定是不行的,还是根据题意,经过原点的直线每扫到一个点必然会将所有的点分为两部分,我们只需维护两个集合的val值即可。这里用的是以y轴作为起始扫描线,顺时针按斜率从大到小扫描,起始就可以分为x>0和x<0两个集合,然后特判在y轴上的点属于哪边会有最优解,接下来开始扫描,对了,得先按斜率从大到小排个序。每扫到一个点就把这个点原属的val集合减去,另一个val集合加上,然后遍历所有点取最优解即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const double eps=1e-8;
const int N=5e4+10;
struct point//定义点
{
double x,y;
ll val;
} p[N] ;
struct line//线
{
point a,b;
};
int cmp(point a,point b)
{
return (a.y/a.x)>(b.y/b.x);
}
int main()
{
int t,n;
scanf("%d",&t);
while(t--)
{
int k=0;
scanf("%d",&n);
ll val,sum1=0,sum2=0,ans=0,tmp1=0,tmp2=0;
double x,y;
for(int i=0; i<n; i++)
{
scanf("%lf%lf%lld",&x,&y,&val);
if(x==0)
{
if(y>0) tmp1+=val;//y轴上的点,有且仅有一个
else tmp2+=val;
}
else p[k].x=x,p[k].y=y,p[k++].val=val;
}
sort(p,p+k,cmp);
for(int i=0; i<k; i++)
{
if(p[i].x>0) sum2+=p[i].val;
else sum1+=p[i].val;
}
ans=max((sum1+tmp1)*(sum2+tmp2),(sum2+tmp1)*(sum1+tmp2));
sum1+=tmp1,sum2+=tmp2;
for(int i=0; i<k; i++)
{
if(p[i].x>0)
{
ans=max(ans,(sum1+p[i].val)*(sum2-p[i].val));
sum1+=p[i].val;
sum2-=p[i].val;
}
else
{
ans=max(ans,(sum1-p[i].val)*(sum2+p[i].val));
sum1-=p[i].val;
sum2+=p[i].val;
}
}
printf("%lld\n",ans);
}
return 0;
}
HDU-6129 Just do it
这道题结束看大牛的题解才发现有惊喜,挺不错的一道题,奈何蒟蒻在做比赛时没有做出来,今早推了一下就补出来 了。。题意:给你一个n个数的序列,每次构造一个前缀异或和序列。求构造m次之后的序列。
比赛最开始看的一道题,结果到最后还是没做出来。上手以为这类题的套路大概是暴力找循环节,于是手推了n较小的情况,发现都符合,但为了保险于是打个表,却发现n越大其循环节呈log增长,这样就没什么想法了。队友在写其他4个题的时候自己手写了前几个数的构造规律,发现dp[i][j]=dp[i-1][j]^dp[i][j-1]。但还是没想法,队友把其他4道比较水的题都做出来之后我暴力写了一发,当然是T了, 于是坐等(以)题(待)解(毙)。关键在于上述转移方程式可以推出:dp[i][j]=dp[i-2^k][j]^dp[i][j-2^k]。知道了这个就很好写了,但二维数组肯定开不下,其实一维的就完全可以了。k=0、1、2、3...的时候,我们就一直在构造当m较小的情况,构造到第m个序列的时候自然已经知道了前面所有的序列了。而任意数m也都是由0+1+2+4+....这样构造的,所以m一直减去其lowbit(m),这里就可以优化到一维了,注意i-lowbit(m)>=0,那么a[i]=a[i]^a[i-lowbit(m)]。
const int N=1e5+10;
int lowbit(int x)
{
return x&(-x);
}
int a[N*2];
int main()
{
int t,n,m;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
a[0]=0;
for(int i=1; i<=n; i++)
scanf("%d",&a[i]);
while(m)
{
int x=lowbit(m);
for(int i=1; i<=n; i++)
if(i-x>=0)
a[i]^=a[i-x];
m-=x;
}
for(int i=1; i<=n; i++)
printf("%d%c",a[i],i==n?'\n':' ');
}
return 0;
}