唉……第二天依然被虐……但是比第一天好一点……我必须负责任的指出:志灿大神出的题比柯黑的不知道靠谱到哪里去了……柯黑出的简直不可做

但是被虐的命运是无法改变的……求各位神犇别D我

黄巨大真是强啊,不愧是福建省现役最强!连A两题之后第三题写了个暴力随机点+最小生成树的多跑了几次竟然各种乱A……还把std给hack了……rank1的巨大神!@陈*瑶

【题目描述】

二维平面上有n个点(xi, yi),现在这些点中取若干点构成一个集合S,对它们按照x坐标排序,顺次连接,将会构成一些连续上升、下降的折线,设其数量为f(S)。如下图中,1->2,2->3,3->5,5->6(数字为下图中从左到右的点编号),将折线分为了4部分,每部分连续上升、下降。

现给定k,求满足f(S) = k的S集合个数。

【输入格式】

第一行两个整数n和k,以下n行每行两个数(xi, yi)表示第i个点的坐标。所有点的坐标值都在[1, 100000]内,且不存在两个点,x坐标值相等或y坐标值相等。

【输出格式】

输出满足要求的方案总数 mod100007的结果。

【样例输入】

5 1

5 5

3 2

4 4

2 3

1 1

【样例输出】

19

【数据范围】

对于10%的数据,n <= 10, k = 1

对于30%的数据,n <= 1000, k = 1

对于50%的数据,n <= 1000, k <= 10

对于100%的数据,n <= 50000,0 < k <= 10

第一题可做……就是带优化的dp。但是我逗比了……考场上没想出方程……幸好我及时orz了hzwer巨大神

n^2*m暴力还是可写的

首先按x坐标sort一下,把y坐标提出来。这基本上没问题

用f[i][j][0/1]表示选了第i个点、一共有j段折线、最后一段是上升(1)或者下降(0)的方案数

这里不能选前i个点,因为这样不能知道第i个点是选了还是没选。

所以f[i][j][1]=Σf[k][j][1]+f[k][j-1][0],其中y[k]>y[i]

f[i][j][0]=Σf[k][j][0]+f[k][j-1][1],其中y[k]<y[i];

具体实现什么的看代码吧

#include<cstdio>
#include<iostream>
#include<algorithm>
#define mod 100007
using namespace std;
struct point{
int x,y;
}p[100001];
inline bool cmp(const point &a,const point &b)
{
return a.x<b.x;
}
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n,m,sum;
int a[100001];
int f[1001][1001][2];
int main()
{
freopen("line.in","r",stdin);
freopen("line.out","w",stdout);
n=read();m=read();
for (int i=1;i<=n;i++)p[i].x=read(),p[i].y=read();
sort(p+1,p+n+1,cmp);
for (int i=1;i<=n;i++)a[i]=p[i].y;
for (int i=1;i<=n;i++)
{
f[i][0][0]=f[i][0][1]=1;
for (int j=1;j<=m;j++)
{ for (int k=1;k<i;k++)
if (a[k]<a[i])
{
f[i][j][1]+=f[k][j][1];
if (j)f[i][j][1]+=f[k][j-1][0];
while(f[i][j][1]>mod) f[i][j][1]-=mod;
}
else
{
f[i][j][0]+=f[k][j][0];
if (j)f[i][j][0]+=f[k][j-1][1];
while(f[i][j][0]>mod) f[i][j][0]-=mod;
}
}
}
for (int i=1;i<=n;i++)
sum=(sum+f[i][m][0]+f[i][m][1])%mod;
printf("%d",sum);
}

那么这样dp时间效率是n^2*m的,肯定要T

所以可以考虑维护一个树状数组、以y为关键字,这样可以优化到n*logn*m

刚考完cf又掉rating 没心情再写了。直接上黄巨大代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define ll long long
#define inf 100000000
#define mod 100007
using namespace std;
inline ll read()
{
ll x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n,m,ans;
int t[15][2][100005];
int f[100005][15][2];//0ΪÉÏÉý1ΪϽµ
struct data{int x,y;}p[100005];
inline bool operator<(data a,data b)
{return a.x<b.x;}
inline int lowbit(int x)
{return x&(-x);}
inline void add(int x,int v,int j,int k)
{
for(int i=x;i<=100000;i+=lowbit(i))
t[j][k][i]=(t[j][k][i]+v)%mod;
}
inline int que(int x,int j,int k)
{
int sum=0;
for(int i=x;i;i-=lowbit(i))
sum=(sum+t[j][k][i])%mod;
return sum;
}
void solve1()
{
for(int i=1;i<=n;i++)
{
f[i][0][0]=f[i][0][1]=1;
for(int j=1;j<i;j++)
for(int k=1;k<=m;k++)
{
if(p[j].y<p[i].y)f[i][k][0]+=f[j][k][0]+f[j][k-1][1];
else f[i][k][1]+=f[j][k][1]+f[j][k-1][0];
f[i][k][0]%=mod;f[i][k][1]%=mod;
}
}
for(int i=1;i<=n;i++)
{
ans=(ans+f[i][m][0])%mod;
ans=(ans+f[i][m][1])%mod;
}
printf("%d\n",ans);
}
void solve2()
{
for(int i=1;i<=n;i++)
{
f[i][0][0]=f[i][0][1]=1;
add(p[i].y,1,0,0);add(p[i].y,1,0,1);
for(int j=1;j<=m;j++)
{
f[i][j][0]+=que(p[i].y-1,j,0)+que(p[i].y-1,j-1,1);
f[i][j][1]+=que(100000,j,1)-que(p[i].y,j,1)+que(100000,j-1,0)-que(p[i].y,j-1,0);
f[i][j][0]%=mod;f[i][j][1]%=mod;
if(f[i][j][1]<0)f[i][j][1]+=mod;
add(p[i].y,f[i][j][0],j,0);add(p[i].y,f[i][j][1],j,1);
}
}
for(int i=1;i<=n;i++)
{
ans=(ans+f[i][m][0])%mod;
ans=(ans+f[i][m][1])%mod;
}
printf("%d\n",ans);
}
int main()
{
freopen("line.in","r",stdin);
freopen("line.out","w",stdout);
n=read();
m=read();
for(int i=1;i<=n;i++)
p[i].x=read(),p[i].y=read();
sort(p+1,p+n+1);
if(n<=1000)solve1();
else solve2();
return 0;
}

你看他写得多好啊

还是我太弱了

【题目描述】

给定n个非负整数A[1], A[2], ……, A[n]。

对于每对(i, j)满足1 <= i < j <= n,得到一个新的数A[i] xor A[j],这样共有n*(n-1)/2个新的数。求这些数(不包含A[i])中前k小的数。

注:xor对应于pascal中的“xor”,C++中的“^”。

【输入格式】

第一行2个正整数 n,k,如题所述。

以下n行,每行一个非负整数表示A[i]。

【输出格式】

共一行k个数,表示前k小的数。

【样例输入】

4 5

1

1

3

4

【样例输出】

0 2 2 5 5

【样例解释】

1 xor 1 = 0 (A[1] xor A[2])

1 xor 3 = 2 (A[1] xor A[3])

1 xor 4 = 5 (A[1] xor A[4])

1 xor 3 = 2 (A[2] xor A[3])

1 xor 4 = 5 (A[2] xor A[4])

3 xor 4 = 7 (A[3] xor A[4])

前5小的数:0 2 2 5 5

【数据范围】

第一个数据点,n <= 1000;

第二个数据点,k = 1;

对于40%的数据,n <= 10000; k <= 10;

对于60%的数据,n <= 20000;

对于100%的数据,2 <= n <= 100000; 1 <= k <= min{250000, n*(n-1)/2};

0 <= A[i] < 231

这题实在是……

首先,n^2暴力是很好搞的。

其次,q=1的情况也是可做的。据鸿巨大说要用trie树搞

最后,来讲一种我在考场上想到的很奇怪的算法(反正能A就是爷)

以样例为例,先把所有数转成2进制:

001

001

011

100

我的做法是首先把第一位是0的和第一位是1的分开,那么就形成了两块。注意到同一块中的数相互异或肯定第一位是0(因为第一位相同),而在第一块中取一个再从第二块中取一个作异或,肯定第一位是1。这样我们证明了从同一块中挑选一定是优于跨越这一块从另外一块选一个拿去异或。比如说,001、001、011被划分成一块,100被划分成另一块。那么显然在同块中的异或结果更优。比如001^001=0,001^011=2,都优于100^001=5,100^011=7。那分成2块以后还能不能再这样分成4块呢?答案是肯定的。

那么推广一下:把数据快排,暴力根据前几位的状态建一棵树,根节点是所有数,左节点是开头是‘0’的数的区间(快排后这些数肯定在一个区间内而不是被离散),右节点是开头是‘1’的数的区间。树的第三层分别是开头是‘00’‘01’‘10’‘11’的数的区间……这样树就建完了。它是长这样的:(画的丑勿喷)

那么显然这棵树最坏情况下有31层即log(maxlongint),对于每一层我们都可以用n^2暴力枚举树节点上的答案,然后sort。这样画的层数越多,n^2的平摊效果越好。然而我们要保证解数>=k,所以要一层上面Σ(len[i]*len[i-1]/2)>=k。显然我们可以保存每一层产生的数字对数,从上往下找到第一个小于k的,我们就直接暴力枚举ans。

比如第一层根节点最多产生4*3/2=6个,超过5

第二层最多产生3*2/2=3个,不到5

所以我们只好从根节点枚举,这样效率n^2了

不过数据完全随机且比较大,应该不会出现恶意去卡的情况。要不然对于极限数据比如任何a[i]都=1的直接特判一下。

ps:我和黄巨大交流的时候我跟他讲了一下,然后他写了一个暴力A了,我还要做死地把建树的for改成二分,结果又wa又t一时爽……我还是太弱了

对于极限数据比如任何a[i]都=1的直接特判一下。

就不贴我写的丑丑的代码了,贴黄巨大的
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define ll long long
#define inf 100000000
using namespace std;
inline ll read()
{
ll x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n,m,num;
int a[100005],b[1000005];
int bin[35],tmp[35][100005];
ll cnt[35];
void solve1()
{
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
b[++num]=(a[i]^a[j]);
sort(b+1,b+num+1);
for(int i=1;i<=m;i++)
printf("%d ",b[i]);
}
void cal(int l,int r,int k)
{
if(l>=r)return;
int tot=0;
for(int i=l;i<=r;i++)
if(tmp[k+1][i]&bin[k])tot++;
int L=l-1,R=l+tot-1;
for(int i=l;i<=r;i++)
if(tmp[k+1][i]&bin[k])tmp[k][++L]=tmp[k+1][i];
else tmp[k][++R]=tmp[k+1][i];
if(k!=0){cal(l,l+tot-1,k-1);cal(l+tot,r,k-1);}
cnt[k]+=(ll)(r-l+1)*(r-l)/2;
}
void print(int l,int r,int k,int x)
{
if(l>=r)return;
if(k==x)
{
for(int i=l;i<=r;i++)
for(int j=i+1;j<=r;j++)
b[++num]=tmp[x+1][i]^tmp[x+1][j];
return;
}
int tot=0;
for(int i=l;i<=r;i++)
if(tmp[k+1][i]&bin[k])tot++;
if(k!=0){print(l,l+tot-1,k-1,x);print(l+tot,r,k-1,x);}
}
void solve2()
{
for(int i=1;i<=n;i++)tmp[31][i]=a[i];
cal(1,n,30);
bool flag=0;
for(int i=30;i>=0;i--)
if(cnt[i]<m){print(1,n,30,i+1);flag=1;break;}
if(!flag)print(1,n,30,0);
sort(b+1,b+num+1);
for(int i=1;i<=m;i++)
printf("%d ",b[i]);
}
int main()
{
freopen("xorit.in","r",stdin);
freopen("xorit.out","w",stdout);
bin[0]=1;for(int i=1;i<=31;i++)bin[i]=bin[i-1]*2;
n=read(),m=read();
for(int i=1;i<=n;i++)
a[i]=read();
if(n<=1000)solve1();
else solve2();
return 0;
}

除此之外,各位大神们还想出了很多其他做法,我承认自己yy根本做不到。

鸿巨大指出:哎这不是“超级钢琴”原题吗?看我写堆+可持久trieA掉它……结果T了三个点。最后鸿巨大还是自豪的说,我的算法是稳定的……只是T了而已……
翁家弈的做法是在正常的两个for里加上剪枝,就是abs(a-b)<=a^b<=abs(a+b)还是什么的忘记了,但是这样可以卡时限A掉。这样应该也算随机化算法。
总之,大神的世界我们怎么会懂……

【题目描述】

给定二维平面上n个整点,求该图的一个直线斯坦纳树,使得树的边长度总和尽量小。

直线斯坦纳树:使所有给定的点连通的树,所有边必须平行于坐标轴,允许在给定点外增加额外的中间节点。

【输入格式】

第一行一个整数n,表示点数。

以下n行,每行两个整数表示点的x,y坐标。

【输出格式】

第一行一个整数m,表示中间节点的个数。

必须满足m <= 10 * n

以下m行,每行2个整数表示中间节点的坐标。

以下n+m-1行,每行2个整数u,v表示编号为u和v的两个节点之间有边直接相连,边的权值为两点的曼哈顿距离,即|x[u] – x[v]|+ |y[u] – y[v]|

输入数据给定的点的编号为1..n,选手输出的中间节点的编号为n+1..n+m

【样例输入】

4

-1 0

0 -1

1 0

0 1

【样例输出】

1

0 0

1 5

2 5

3 5

4 5

【格式说明】

选手可使用test.exe对数据进行测试

在命令行下使用“test x”即可测试rsmtx.in和rsmtx.out

(注:x必须是一个字符,即“test 1234”等价于“test 1”)

【题目描述】

给定二维平面上n个整点,求该图的一个直线斯坦纳树,使得树的边长度总和尽量小。

直线斯坦纳树:使所有给定的点连通的树,所有边必须平行于坐标轴,允许在给定点外增加额外的中间节点。

【输入格式】

第一行一个整数n,表示点数。

以下n行,每行两个整数表示点的x,y坐标。

【输出格式】

第一行一个整数m,表示中间节点的个数。

必须满足m <= 10 * n

以下m行,每行2个整数表示中间节点的坐标。

以下n+m-1行,每行2个整数u,v表示编号为u和v的两个节点之间有边直接相连,边的权值为两点的曼哈顿距离,即|x[u] – x[v]|+ |y[u] – y[v]|

输入数据给定的点的编号为1..n,选手输出的中间节点的编号为n+1..n+m

【样例输入】

4

-1 0

0 -1

1 0

0 1

【样例输出】

1

0 0

1 5

2 5

3 5

4 5

【格式说明】

选手可使用test.exe对数据进行测试

在命令行下使用“test x”即可测试rsmtx.in和rsmtx.out

(注:x必须是一个字符,即“test 1234”等价于“test 1”)

这题前4个点n=8,是状压dp:f[x][y][s]表示当前过点(x,y),点之间的联通性是s的最小边数,然后乱搞

5到8个点是插头dp……根本不会

最后两个点暴搜吧

结果黄巨大写的神rand居然拿下70分,而且最后两个点还把志灿hack了……真不知是该膜拜呢还是膜拜呢还是膜拜

福建省队集训被虐记——DAY2的更多相关文章

  1. 福建省队集训被虐记——DAY4

    啊啊啊啊啊啊第四天考的是我最不擅长的图论--整个人都斯巴达了 //另外不得不吐槽下午的上课讲的都是网络流--难道是出题人觉得图论里除了网络流以外的其他算法都没有人权图样图森破? 愚蠢的算法(clums ...

  2. 福建省队集训被虐记——DAY3

    昨天没写--今天补上吧 一如既往的跪了 棋盘 [问题描述] 给出一个N*M的方格棋盘,每个格子里有一盏灯和一个开关,开始的时候,所有的灯都是关着的.用(x, y)表示第x行,y列的格子.(x, y)的 ...

  3. 福建省队集训被虐记——DAY1

    今天算是省冬的第一天--早上柯黑出题,说是"信心欢乐赛",其实是"使你失去信心.不再欢乐的比赛" 顺便orz一下来看这篇文章的各路神犇--求轻虐 水题 (py. ...

  4. zju 校队选拔 被虐记

    选拔已经开始了三天才想起来写游记 QAQ.. 7.12 弱弱的Sky_miner来到了ZJU,过程中被热成狗... 然后见到了无数大二大三的大佬们,过程中被热成狗... 后来听靖哥哥说集训的注意事项, ...

  5. JS省队集训记

    不知不觉省队集训已经结束,离noi也越来越近了呢 论考前实战训练的重要性,让我随便总结一下这几天的考试 Day 1 T1 唉,感觉跟xj测试很像啊?meet in middle,不过这种题不多测是什么 ...

  6. HN2018省队集训

    HN2018省队集训 Day1 今天的题目来自于雅礼的高二学长\(dy0607\). 压缩包下载 密码: 27n7 流水账 震惊!穿着该校校服竟然在四大名校畅通无阻?霸主地位已定? \(7:10\)从 ...

  7. 2018HN省队集训

    HNOI2018省队集训 Day 1 流水账 T1 tree 换根+求\(lca\)+求子树和,一脸bzoj3083遥远的国度的既视感.子树和讨论一下就好了,\(lca\)?也是大力讨论一波. 先写了 ...

  8. 2017FJ省队集训 游记

    2017FJ省队集训 游记 又是一篇流水账 Day 1 今天是省队集训的第一天.早上骑车去八中,到的时候汗流太多浑身湿透被杨哥哥和runzhe2000 d了,一个说我去游泳了一个说我打球了...流完汗 ...

  9. [2018HN省队集训D9T1] circle

    [2018HN省队集训D9T1] circle 题意 给定一个 \(n\) 个点的竞赛图并在其中钦定了 \(k\) 个点, 数据保证删去钦定的 \(k\) 个点后这个图没有环. 问在不删去钦定的这 \ ...

随机推荐

  1. poj3358:欧拉定理

    又是一道用欧拉定理解的题..嗯,关键还是要建好方程,注意一些化简技巧 题目大意: 给定一个由 p / q 生成的循环小数,求此循环小数在二进制表示下的最小循环节以及不是循环节的前缀 思路: 小数化为二 ...

  2. Abstract Methods and Classes

    阅读了Java的官方Doc,在此总结如下. Abstract Class & Method In jave, "abstract" can be a modifier to ...

  3. (转)iOS7界面设计规范(3) - UI基础 - 启动与退出

    周二晚间来第三发,搞得好像今天是周六的赶脚.发掉之后再奖励自己一点冰啤酒吧,然后扑床去.天气热起来了,各位注意防暑降温呗.走起. 重要:这是针对于正在开发中的API或技术的预备文档(预发布版本).虽然 ...

  4. PHP设计模式笔记四:适配器模式 -- Rango韩老师 http://www.imooc.com/learn/236

    适配器模式 1.适配器模式,可以将截然不同的函数接口封装成统一的API 2.实际应用举例,PHP的数据库操作有mysql.mysqli.pdo三种,可以用适配器模式统一成一致,类似的场景还有cache ...

  5. Linux 时间同步配置(转)

    一. 使用ntpdate 命令 1.1 服务器可链接外网时 # crontab -e 加入一行: */1 * * * * ntpdate 210.72.145.44 210.72.145.44 为中国 ...

  6. RHEL-resolv.conf文件修改后重启被还原

    修改resolve.conf文件之后,reboot或service restart network时,修改的内容被还原.关闭NetworkManager即可.# chkconfig |grep Net ...

  7. Stm32高级定时器(二)

    Stm32高级定时器(二) 1 主从模式:主?从? 谈论主从,可知至少有两个以上的触发或者驱动信号,stm32内部有多个定时器,可以相互之间驱动或者控制. 主模式:定时器使能只受驱动时钟控制或者输出控 ...

  8. ie8 hack

    1.‘\9’: eg:.test { color/*\**/: blue\9 }.header {width:300px;} /* 所有浏览器*/.header {width/*\**/:330px\ ...

  9. C# Serializable学习

    先上代码,感觉这个功能很给力啊. class Program { static void Main(string[] args) { //下面代码将对象Person进行序列化并存储到一个文件中 Per ...

  10. OpenGL ES 2.0 剪裁测试

    剪裁测试:可以在渲染时用来限制绘制区域,通过此技术可以在屏幕(帧缓冲)上指定一个矩形区域. //启用剪裁测试 GLES20.glEnable(GL10.GL_SCISSOR_TEST); //设置区域 ...