机房测试1:big(贪心+Trie树)

题目:

分析:

考虑最暴力的办法:枚举选哪个数,枚举对手在哪个时间变化,然后统计答案。

对于异或这一类问题,考虑区间异或可以抵消重复区间,维护一个前缀异或和:pre[i]表示1~i的异或和,suf[i]表示i~n的异或和。

将对手的式子化简,2*x即将x向左移一位,/( 2^n )为向右移n位,+2*x ,%2^n类似。

模拟一下:12345 -> 123450 -> 123451 -> 23451

每次枚举对手要变的时间i,最后的值即为:work ( pre[i] ^ x ) ^ suf[i+1]    (work是按照上述式子的转换)

枚举x的复杂度太高,其实可以先将 work(pre[i])^ suf [i+1] 预处理出来,用trie树贪心求x。

为什么是对的?

原式转换成:work( pre[i]  )^ suf[i+1]  ^ work( x )  其实就是将前半部分放入trie树,贪心求后半部分的最大值。

注意:trie储存的是对手可以翻转的值 ,如果对手只有1(或只有0), 那么我们可以选择相反的 ,获得这一位的1 ,否则对手两个都有,对手会选择最优策略 ,我们不会收获 。

#include<bits/stdc++.h>
using namespace std;
#define N 100005
#define ri register int
int pre[N],go[N*30][3],suf[N],x[N],ans=0,num=0,a[N],n,ndnum=0;
int calc(int y)
{
    return ( y*2/(1<<n) + 2*y ) % (1<<n);
}
void add(int y)
{
    int now=0;
    for(ri i=n-1;i>=0;--i){
        int xx=(y>>i)&1;
        if(!go[now][xx]) go[now][xx]=++ndnum;
        now=go[now][xx];
    }
}
void dfs(int now,int dep,int maxn)
{
    if(dep==0){
        if(maxn==ans) num++;
        else if(maxn>ans) ans=maxn,num=1;
        return ;
    }
    //如果对手只有1 那么我们可以选择相反的 获得这一位的1
    if(!go[now][0]) dfs(go[now][1],dep-1,maxn^(1<<(dep-1)));//dep-1是因为二进制是从0开始的 而这里dep从1开始
    else if(!go[now][1]) dfs(go[now][0],dep-1,maxn^(1<<(dep-1)));
    else{//如果对手两个都有 对手会选择最优策略 我们不会收获
        dfs(go[now][1],dep-1,maxn);
        dfs(go[now][0],dep-1,maxn);
    }
}
int main()
{
    freopen("big.in","r",stdin);
    freopen("big.out","w",stdout);
    int m;
    scanf("%d%d",&n,&m);
    for(ri i=1;i<=m;++i) scanf("%d",&a[i]),pre[i]=pre[i-1]^a[i];
    for(ri i=m;i>=1;--i) suf[i]=suf[i+1]^a[i];
    for(ri i=0;i<=m;++i) x[i]=calc(pre[i])^suf[i+1],add(x[i]);//trie储存的是对手可以翻转的值
    dfs(0,n,0);
    printf("%d\n%d\n",ans,num);
}
/*
3
2 3
*/

原文地址:https://www.cnblogs.com/mowanying/p/11604598.html

时间: 2024-07-31 00:11:20

机房测试1:big(贪心+Trie树)的相关文章

HDU4825 Xor Sum(贪心+Trie树)

今天本来想写一个可持久化Trie树,发现这道题一直没做就补上了. 其实思路很简单,假如说两个数,和同一个数异或,很显然,由于进制,高位上的一个1可以大于低位上所有1,所以即使后面的情况再糟糕,也比取后面好的值高(其实就是1000比0111大) 所以可以建一个01线段树,从高往低插入一个数,比较时取反即可^_^ 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace st

[CSP-S模拟测试]:Race(数学+Trie树)

题目描述 一年一度的运动会开始了.有$N$个选手参赛,第$i$个选手有一个能力值(保证$A[i]$两两不同),比赛一共进行了天.在第$j$天($0\leqslant j\leqslant 2^{m-1}$)的比赛中,第$i$个选手的得分为$A[i]\ xor\ j$,然后从大到小排名,排名为$x$($x$从$0$开始)的同学会获得的积分,你需要求出每个同学最后总的积分和$q[i]$模${10}^9+7$的结果$p[i]$.为了避免输出文件过大,你只要输出$p[i]$的异或和即可. 输入格式 第一

机房测试:race(trie)

题目: 分析: 先不考虑天数的限制,直接对每一个人建一颗trie. 对于每一个人来说,他的x的贡献来源于trie树上所有在他右边的点(都比他大). 将每一个子树所有的叶子结点记为f,x^2=(f1+f2+……fx)^2 将右式拆开看:f i *f i + f i * f j *2(枚举i,j统计贡献,*2是因为 i 和 j 可以交换) 再加上天数的限制:每一个人的A[i]异或上天数 j,相当于trie树的形态发生改变了(01边交换) 对于1来说,又多了一部分贡献,也就是说,对于右子树来说,当且仅

[bzoj4567][Scoi2016][背单词] (贪心+trie树)

Description Lweb 面对如山的英语单词,陷入了深深的沉思,“我怎么样才能快点学完,然后去玩三国杀呢?”.这时候睿智 的凤老师从远处飘来,他送给了 Lweb 一本计划册和一大缸泡椒,他的计划册是长这样的: ————— 序号  单词 ————— 1 2 …… n-2 n-1 n ————— 然后凤老师告诉 Lweb ,我知道你要学习的单词总共有 n 个,现在我们从上往下完成计划表,对于一个序号为 x 的单词(序号 1...x-1 都已经被填入): 1) 如果存在一个单词是它的后缀,并且

利用Trie树求多个字符串编辑距离的进一步优化

1.引言 题目的意思应该是:在一个给定的字典中,求与给定的字符串的编辑距离不大于2的所有的单词.原先写过两片关于此问题的文章,那两片篇章文章给出两种解决思路:其一是暴力求解法,这种方法最容易想到.就是将词典中的词一一与给定的字符串计算编辑距离,不大于2的输出,大于2的舍弃,这种方法思路简单但是很费时间.其二根据词典中这些词之间的编辑距离建立一个以单词为节点的Trie树,遍历的时候,通过计算根节点与给定字符串的编辑距离就可以排除掉一部分分支了,然后继续计算该字符串与剩余的分支的根的编辑距离,继续排

基于 trie 树的最长匹配分词测试

测试一个基于trie树的分词,没有应用任何统计模型,分词的效率估计会很高但是分词准确率很差. reference http://www.hankcs.com/program/java/tire-tree-participle.html https://github.com/ansjsun/tree_split

T2 选ID trie树

T2 选ID Description ? 机房似乎有许多人没有 ID,热心同志小 A 为了服务人民,所有决定帮大家找一个合适的 ID. ? 小 A 觉得一个合适的 ID,和这个人的相关程度应该是比较高的,就像他的 ID 里有他的名字缩写一样.为了量化这个相关程度,他定义一个人的名字 \(S\) 和他的 ID \(T\) 的匹配值的大小为\(lcp\)(\(S\),\(T\))?.现在有 \(n\) 个人,小 A 想好了 \(n\) 个 ID,他想知道如果把 ID 分配给机房众人,最后能够得到的最

Trie树详解(转)

特别声明 本文只是一篇笔记类的文章,所以不存在什么抄袭之类的. 以下为我研究时参考过的链接(有很多,这里我只列出我记得的): Trie(字典树)的应用--查找联系人 trie树 Trie树:应用于统计和排序 牛人源码,研究代码来源 1.字典树的概念 字典树,因为它的搜索快捷的特性被单词搜索系统使用,故又称单词查找树.它是一种树形结构的数据结构.之所以快速,是因为它用空间代替了速度. 2.字典树的特点: 字典树有三个基本性质: 1.根节点不包含字符,除根节点外每一个节点都只包含一个字符2.从根节点

ifrog-1028 Bob and Alice are playing numbers(trie树)

题目链接: Bob and Alice are playing numbers DESCRIPTION Bob and his girl friend are playing game together.This game is like this: There are nn numbers. If op = 11,Bob wants to find two numbers aiai and ajaj,that aiai & ajaj will become maximum value. If