实际得分:100+0+0=100

T1

右上角是必败态,然后推下去

发现同行全是必胜态或全是必败态,不同行必胜必败交叉

列同行

所以n,m 只要有一个是偶数,先手必胜

#include<cstdio>

using namespace std;

int main()
{
freopen("star.in","r",stdin);
freopen("star.out","w",stdout);
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(!n) return ;
if(!(n&) || !(m&)) puts("Yuri");
else puts("Chito");
}
}

T2

k=1 暴力:

可持久化trie树 求 异或最大值

#include<cstdio>
#include<iostream>
#include<algorithm> #define N 50001 const int mod=1e9+; using namespace std; int bit[]; int a[N]; int root[N],ch[N*][],cnt[N*],tot; void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
} void insert(int pre,int &now ,int dep,int x)
{
if(!now) now=++tot;
cnt[now]=cnt[pre]+;
if(dep<) return;
int p= (x&bit[dep])>;
ch[now][p^]=ch[pre][p^];
insert(ch[pre][p],ch[now][p],dep-,x);
} int query(int pre,int k,int dep,int x)
{
if(dep<) return ;
int p= (x&bit[dep])>;
if(cnt[ch[k][p^]]-cnt[ch[pre][p^]]) return bit[dep]+query(ch[pre][p^],ch[k][p^],dep-,x);
return query(ch[pre][p],ch[k][p],dep-,x);
} int main()
{
freopen("war.in","r",stdin);
freopen("war.out","w",stdout);
bit[]=;
for(int i=;i<=;++i) bit[i]=bit[i-]<<;
int n,k;
read(n); read(k);
for(int i=;i<=n;++i)
{
read(a[i]);
insert(root[i-],root[i],,a[i]);
}
int ans=;
for(int i=;i<=n;++i) ans=max(ans,query(root[],root[n],,a[i]));
cout<<ans%mod;
}

所有数不超过1023暴力:

预处理所有 i^j的结果,cnt[i]表示第i个数的个数

这样每一种 异或 值出现的次数=cnt[i]*cnt[j]

从大到小枚举,直至k个即可

#include<cstdio>
#include<iostream>
#include<algorithm> #define N 50001 const int mod=1e9+; using namespace std; int cnt[]; struct node
{
int i,j,y;
}e[*+]; void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
} bool cmp(node p,node q)
{
return p.y>q.y;
} int main()
{
freopen("war.in","r",stdin);
freopen("war.out","w",stdout);
int n,x; long long k;
read(n); scanf("%I64d",&k);
for(int i=;i<=n;++i) read(x),cnt[x]++;
int tot=;
for(int i=;i<;++i)
for(int j=i+;j<;++j)
e[++tot].i=i,e[tot].j=j,e[tot].y=i^j;
sort(e+,e+tot+,cmp);
int ans=;
for(int i=;i<=tot;++i)
{
ans=(ans+min(k,1ll*cnt[e[i].i]*cnt[e[i].j])*e[i].y%mod)%mod;
k-=min(k,1ll*cnt[e[i].i]*cnt[e[i].j]);
if(!k) break;
}
cout<<ans;
}

满分做法:

二分出一个最大的t,t满>t的数至少有k个

然后查询所有异或值 >t 的数的和,最后在减去 属于前k大的数的和

二分检验与查询均在trie树上进行

查询>t的数的个数:

枚举n个数a[i],累积 与每一个a[i] 异或后 >t 的个数

对于每一个a[i],设现在是第j位

如果t的第j位是0,那么累加第j位与a[i] 不同 的数的个数,trie树上的当前位置转到 第j位与a[i] 的第j位相同的位置

因为所以在第j位就分出大小的数都以累加,继续找第j位分不出大小的数

如果t的第j位是1,什么都不累加,trie树上的当前位置 转到 第j位与a[i] 不同的 位置

因为如果这一位与t的第j位相同,异或得0,一定<t,如果不同,第j位 分不出大小,继续往后走

累积所有>t的数的和:

还是枚举n个数a[i],累积 与每一个 a[i] 异或后>t 的数的和

累积方法思路与上面差不多

如果t的第j位是0,那么就累计 当前位置 所有的与a[i] 异或 为1的数的和,当前位置转到 与a[i]的第j位相同的位置

如果t的第j为是1,那么当前位置 转到与a[i]的第j位不同的位置

注意每一对合法的数会使用两次,所以累计个数 和 总和 时 注意 除以2

#include<cstdio>
#include<iostream> using namespace std; #define N 50001 const int mod=1e9+;
const int inv=5e8+; long long k; int n; int a[N],trie[N*][],all[N*][],tot=; int cnt[N*]; int bit[]; void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
} void insert(int x)
{
int now=,d;
for(int i=;i>=;--i)
{
d=(x&bit[i])>;
if(!trie[now][d]) trie[now][d]=++tot;
now=trie[now][d];
cnt[now]++;
for(int j=;j>=;--j)
if(x&bit[j]) all[now][j]++;
}
} int upper(int x,int t)
{
int pos=,d,sum=;
for(int i=;i>=;--i)
{
d=(x&bit[i])>;
if(!(t&bit[i])) sum+=cnt[trie[pos][d^]],pos=trie[pos][d];
else pos=trie[pos][d^];
// if(t==754974719 && x==962029906) cout<<i<<' '<<sum<<' '<<trie[pos][d^1]<<'\n';
}
return sum;
} int query(int x,int t)
{
int pos=,d,sum=;
for(int i=;i>=;--i)
{
d=(x&bit[i])>;
if(!(t&bit[i]))
{
for(int j=;j>=;--j)
if(x&bit[j]) sum=(sum+1LL*(cnt[trie[pos][d^]]-all[trie[pos][d^]][j])*bit[j]%mod)%mod;
else sum=(sum+1LL*all[trie[pos][d^]][j]*bit[j]%mod)%mod;
pos=trie[pos][d];
}
else pos=trie[pos][d^];
}
//cout<<sum<<'\n';
return sum; } long long check(int x)
{
long long sum=;
for(int i=;i<=n;i++)
{
sum+=upper(a[i],x);
//if(x==754974719) cout<<i<<' '<<sum<<'\n';
}
return sum/;
} int main()
{
freopen("war.in","r",stdin);
freopen("war.out","w",stdout);
read(n); scanf("%I64d",&k);
bit[]=;
for(int i=;i<=;++i) bit[i]=bit[i-]<<;
for(int i=;i<=n;++i)
{
read(a[i]);
insert(a[i]);
// cout<<i<<' '<<tot<<'\n';
}
int l=,r=,mid,tmp=-;
while(l<=r)
{
mid=l+r>>;
if(check(mid)>=k) l=mid+,tmp=mid;
else r=mid-;
// cout<<mid<<' '<<check(mid)<<'\n';
}
int ans=;
if(tmp!=-)
{
long long res=k-check(tmp);
for(int i=;i<=n;i++)
{
ans+=query(a[i],tmp),ans%=mod;
// cout<<ans<<'\n';
}
ans=1LL*ans*inv%mod;
ans=(ans+1LL*res*(tmp+)%mod)%mod;
}
else
{
for(int i=;i<=n;i++) ans+=query(a[i],),ans%=mod;
ans=1LL*ans*inv%mod;
}
cout<<ans;
//for(int i=1;i<=tot;i++) cout<<i<<' '<<cnt[i]<<'\n';
}

T3

因为k<=10 所以线段树维护区间前10大

合并的时候,用了类似于归并排序时用的 两个指针,扫一遍即可

#include<cstdio>
#include<cstring>
#include<iostream> using namespace std; #define N 100001 int f[N<<]; struct node
{
int mx[]; node() { memset(mx,,sizeof(mx));} node operator + (node p)
{
node t;
int a=,b=,c=;
while(c<=) t.mx[c++]=mx[a]>p.mx[b] ? mx[a++] : p.mx[b++];
return t;
}
}tr[N<<]; void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
} void build(int k,int l,int r)
{
if(l==r) { read(tr[k].mx[]); return; }
int mid=l+r>>;
build(k<<,l,mid);
build(k<<|,mid+,r);
tr[k]=tr[k<<]+tr[k<<|];
} void down(int k)
{
f[k<<]+=f[k];
f[k<<|]+=f[k];
for(int i=;i<=;++i)
{
if(tr[k<<].mx[i]) tr[k<<].mx[i]+=f[k];
if(tr[k<<|].mx[i]) tr[k<<|].mx[i]+=f[k];
}
f[k]=;
} node query(int k,int l,int r,int opl,int opr)
{
if(l>=opl && r<=opr) return tr[k];
if(f[k]) down(k);
int mid=l+r>>;
if(opr<=mid) return query(k<<,l,mid,opl,opr);
if(opl>mid) return query(k<<|,mid+,r,opl,opr);
return query(k<<,l,mid,opl,opr)+query(k<<|,mid+,r,opl,opr);
} void change(int k,int l,int r,int opl,int opr,int w)
{
if(l>=opl && r<=opr)
{
for(int i=;i<=;i++)
if(tr[k].mx[i]) tr[k].mx[i]+=w;
f[k]+=w;
return;
}
if(f[k]) down(k);
int mid=l+r>>;
if(opl<=mid) change(k<<,l,mid,opl,opr,w);
if(opr>mid) change(k<<|,mid+,r,opl,opr,w);
tr[k]=tr[k<<]+tr[k<<|];
} int main()
{
freopen("noname.in","r",stdin);
freopen("noname.out","w",stdout);
int n,m;
read(n); read(m);
build(,,n);
int op,l,r,w;
while(m--)
{
read(op); read(l); read(r); read(w);
if(!op)
{
if(r-l+<w) cout<<-<<'\n';
else cout<<query(,,n,l,r).mx[w]<<'\n';
}
else change(,,n,l,r,w);
}
}

错误:

将前10大全部放到一个结构体里,query时直接返回结构体

合并的时候 重载的 加号 运算符

所以 标记 不能放到 结构体里

下传标记的时候,只传前10大,但应先判断是否具有第i大

2017 清北济南考前刷题Day 3 morning的更多相关文章

  1. 2017 清北济南考前刷题Day 7 afternoon

    期望得分:100+100+30=230 实际得分:100+100+30=230 1. 三向城 题目描述 三向城是一个巨大的城市,之所以叫这个名字,是因为城市中遍布着数不尽的三岔路口.(来自取名力为0的 ...

  2. 2017 清北济南考前刷题Day 1 afternoon

    期望得分:80+30+70=180 实际得分:10+30+70=110 T1 水题(water) Time Limit:1000ms   Memory Limit:128MB 题目描述 LYK出了道水 ...

  3. 2017 清北济南考前刷题Day 3 afternoon

    期望得分:100+40+100=240 实际得分:100+40+100=240 将每个联通块的贡献乘起来就是答案 如果一个联通块的边数>点数 ,那么无解 如果边数=点数,那么贡献是 2 如果边数 ...

  4. 2017 清北济南考前刷题Day 4 afternoon

    期望得分:30+50+30=110 实际得分:40+0+0=40 并查集合并再次写炸... 模拟更相减损术的过程 更相减损术,差一定比被减数小,当被减数=减数时,停止 对于同一个减数来说,会被减 第1 ...

  5. 2017 清北济南考前刷题Day 7 morning

    期望得分:100+50+20=170 实际得分:10+50+20=80 1. 纸牌 题目描述 在桌面上放着n张纸牌,每张纸牌有两面,每面都写着一个非负整数.你的邪王真眼可以看到所有牌朝上的一面和朝下的 ...

  6. 2017 清北济南考前刷题Day 6 afternoon

    期望得分:100+100+30=230 实际得分: 正解: 枚举最高的位,这一位m是1但实际用了0 然后剩余的低位肯定是 正数就用1,负数用0 考场思路:数位DP #include<cstdio ...

  7. 2017 清北济南考前刷题Day 6 morning

    T1 贪心 10 元先找5元 20元 先找10+5,再找3张5 #include<cstdio> using namespace std; int m5,m10,m20; int main ...

  8. 2017 清北济南考前刷题Day 5 afternoon

    期望得分:100+100+30=230 实际得分:0+0+0=30 T1 直接模拟 #include<cstdio> #include<iostream> using name ...

  9. 2017 清北济南考前刷题Day 5 morning

    期望得分:100+100+0=200 实际得分: 坐标的每一位不是0就是1,所以答案就是 C(n,k) #include<cstdio> #include<iostream> ...

随机推荐

  1. 【CJOJ P1957】【NOIP2010冲刺十模拟赛】数字积木

    [NOIP2010冲刺十模拟赛]数字积木 Description 小明有一款新式积木,每个积木上都有一个数,一天小明突发奇想,要是把所有的积木排成一排,所形成的数目最大是多少呢? 你的任务就是读入n个 ...

  2. 【洛谷1541】【CJOJ1087】【NOIP2010】乌龟棋

    题面 Description 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游戏要求玩家控制一个乌 ...

  3. POJ1741

    树分治,每次把每个点的deep取出,排序...尺取法... # include <stdio.h> # include <stdlib.h> # include <ios ...

  4. Delphi关于TAdvStringGrid控件颜色的设置

    FixedFont-Color 标题行和列字体的颜色 Font-color 单元格字体的颜色Visual-color 整个表格的背景色填充

  5. 【BZOJ3529】【SDOI2014】数表

    Time Limit: 1000 ms Memory Limit: 512 MB Description 有一张n×m的数表,其第i行第j列 (1≤i≤n,1≤j≤m)的数值为能同时整除i和j的所有自 ...

  6. linux下主机用户管理(完整详情)

    (一) 创建新用户 useradd命令(也可以使用adduser)用来创建新的用户帐号,其命令格式如下: 表4-19 useradd命令常用选项 常用现象意 义 -d设置新用户的登陆目录 -e设置新用 ...

  7. 九度OJ题目1105:字符串的反码

    tips:scanf,cin输入字符串遇到空格就停止,所以想输入一行字符并保留最后的"\0"还是用gets()函数比较好,九度OJ真操蛋,true?没有这个关键字,还是用1吧,还是 ...

  8. @Controller 类中初始化问题解决办法

    在Controller类中常常遇到有些参数需要初始化,甚至有些只允许初始化一次,而Controller类不像servelet类可以调用init()函数进行初始化,这里想到的办法是设置标记值,让初始化部 ...

  9. Jquery入门(初学者易懂)

    一.定义 jQuery是一个快速.简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScript代码库(或JavaScript框架).jQuery设计的宗旨是"w ...

  10. day1 安装jdk8环境及第一个java程序

    安装jdk8 第一步:下载jdk安装包,我们这里下载orical官网的jdk8版本.