CTYZ信心赛T5 题解

吐槽ing:

一道有趣的二进制题

注意加粗部分是限制条件

我们先考虑暴力分\(40\)分:

首先那个\(Fight\)值一看就知道是二进制。

对于这个暴力分,应该是一种很暴力(废话)的解法,我们直接从\(b\)向\(a\)枚举,然后判断这一个数合不合法,如果合法,就+1,直到找到第\(k\)大,输出答案即可。

考虑\(100pts:\)

这里我们就要开始讨论二进制算法了。

首先我们考虑巨佬站队方式的限制,对于每个询问\([a,b]\),假设巨佬的\(Fight\)值是\(p\),若\(p>b\),那区间\([b,p]\)就没有作用了,我们的查询区间就直接缩成了\([a,min_{b,p-1}]\),这一个限制条件就解决了。

我们再考虑巨佬的站队对蒟蒻的约束作用(即限制了某些位必须是0):

首先我们假设没有这个条件,很显然的,如果第\(i\)大的站队方式的\(Fight\)值是\(j\),那么第\(i+1\)大的站队方式的\(Fight\)值就是\(j-1\)(二进制转十进制),

接着我们再考虑存在某些位必须是\(0\)的情况:

这里的方法是把所有有约束条件的\(0\)删去,得到一个新的,没有约束条件的数。

比如这里有一个第\(i\)大的数的二进制数,其中所有\(0\)都是被限制了的

1 0 1 0 1 0

我们把所有被限制的0删去,得到一个没有被限制的数:

1 1 1

显然这个\(Fight\)值是7,求第\(i+1\)大的数时,我们将7-1,得到6.

1 1 0

然后,我们再把刚才去掉的0加回去

1 0 1 0 0 0

这就是我们要找的数。

关于删除操作,我是这样做的,假设我们要删除下面这个二进制的第3个数:

1 1 1 1 1 1
      ^

我们先把后2位取下来:

1 1 1 1 0 0
s = 1 1

再删除第3位:

1 1 1 0 0 0

整体右移一位,在把\(s\)搬回去。

插入也是同理(改成左移)

具体代码实现(时间复杂度\(O(1)\)):

void del(LL c)
{
    LL o = c - 1;
    s = ((((s & (~ c)) & (~ o)) >> 1) ^ (s & o));
}
void insert(LL c)
{
    LL o = c - 1;
    x = (((x & (~ o)) << 1) ^ (x & o));
} 

然后还有一个问题就是,我们首先要找到满足\([a,min_{b,p-1}]\)的最大值(知道了以后就可以解题了)。

我们同样先不考虑后面的限制,我们把\(min_{b,p-1}\)和\(p\)列出来从高位到低位枚举,假设蒟蒻的站队方式最大值为\(r\),如果我们枚举到一位,满足这一位\(p\)是1,\(min_{b,p-1}\)也是1,由于约束,则蒟蒻的站队在这一位上必须是0,由于是从高位往低位枚举,则高位上肯定没有这种情况(否则就不会出现在这里了),那\(r\)在这位上肯定是0,这时,可以发现,无论后面取什么数,其结果都比\(min_{b,p-1}\)小!那我们的\(r\)值就可以取到这位是0,后面都是1的情况。

对于其他情况,不难发现,我们必须要取\(min_{b,p-1}\)所在的值才能保证最大。

最后,找到了\(r\)后,我们去除限制条件,把所有巨佬所在值为1的权位上的值改为0,我们就找到了最大值。

代码也不长(甚至连数组都不用开),但是如果没思路的话,代码不一定看得懂:

#include<cstdio>
#include<iostream>
#define LL unsigned long long
using namespace std;
LL n,m,t,q;
LL p,a,b,k,s,x;
void del(LL c)
{
    LL o = c - 1;
    s = ((((s & (~ c)) & (~ o)) >> 1ll) ^ (s & o));
}
void getmax()
{
    LL j = (1ll << (n - 1));
    for( ;j ; (j >>= 1))
      if((b & j) && (p & j)) break;
      if(!j) k = b;
      else k = ((b & (~ j)) | (j - 1));
    j = (1ll << (n - 1));
    for(; j; (j >>= 1))
      if(p & j) k = (k & (~ j));
    j = (1ll << (n - 1));s = k;
    for(; j; (j >>= 1))
      if((k & (~ (j - 1))) && (p & j)) del(j);
}
void insert(LL c)
{
    LL o = c - 1;
    x = (((x & (~ o)) << 1ll) ^ (x & o));
}
int main()
{
    scanf("%lld%lld", &n,&m);
    for(LL i = 0;i<n;++i)
    {
        scanf("%lld", &t);
        p |= (t << i);
    }
    while(m --)
    {
        scanf("%lld%lld%lld",&a,&b,&q);
        b = min(p-1, b);
        getmax();
        x = s - q + 1;
        for(LL j = 1;j <= (1ll << n);j <<= 1)
          if(p & j) insert(j);
         if(x < a|| x>p) printf("POOR AFO!\n");
         else printf("%lld\n", x % 20031102);
    }
}

原文地址:https://www.cnblogs.com/dwqhca/p/10185318.html

时间: 2024-08-30 17:28:53

CTYZ信心赛T5 题解的相关文章

第七届省赛赛前交流赛部分题解

A题: Yougth's Game[Ⅲ]( 区间dp ) 这是在省赛前热身赛出的题目,可能是题目中有用到博弈的思想,很多人都在做,而且在尝试暴力.但是没有人往dp的方向上想. 题目类型:动态规划+博弈 分析:题意描述的很清楚,就是选择在两端取数,当前取的数不仅能够影响下一次的结果,而且能够影响后面的结果...又是一个求最优值,那么是不是可以往dp的方向上想了.区间dp 定义状态dp[ i ] [ j ] 为从 i 到 j 上A的得分,那么B的得分就是sum(i,j)-dp[ i ] [ j ]

8.25重庆南开CSP信心赛

8.25重庆南开CSP信心赛 A.填数字 时间限制:1s空间限制:128MB 题面描述信竞队的同学们在一个N*N的方格矩阵上填数字.开始时,所有矩阵里的数字都是0. 同学们一共给 个子矩阵填了数字,每次填的数都是从 这区间中选一个数字,然后给对应矩阵全部填上该数字.比如:第1步,选了一个子矩阵,将数字2填上:2 2 2 02 2 2 02 2 2 00 0 0 0第2步,选了一个子矩阵,将数字7填上:2 2 2 02 7 7 72 7 7 70 0 0 0第3步,选了一个子矩阵,将数字3填上:2

2016 SCNUCPC 校赛非官方题解

我要举报本次校赛出题人的消极出题!!! A. 树链剖分数据结构板题 B. The background of water problem 题目大意(大写加粗的水题):给定$N$个学生和他们$K$个科目的成绩$S_i$,再给出各科目$K_i$的权重顺序$Q_i$,求排名之后,拥有id为$X$的是哪个学生. 基本思路:虽然$K$只有$10$,$S$只有$100$,但有M组查询,所以当然不能开个long long去hash每个学生.我们简单点,开个结构体,排个序,就好了. 参考代码: 官方代码(将成绩

2015 ACM-ICPC 北京赛区 网络赛 部分 题解

由于博主水平及智商不足,所以暂时只能放出下列的题目的题解. A B D F G H 需要其他题解请自行前往 http://talk.icpc-camp.org/ 题目地址:hihocoder 1227-1236 A.  The Cats' Feeding Spots 题意:给出M个点,求以其中一个点为圆心,最小半径的圆,使得这个圆里恰好有N个点. (半径一定要是整数,且点不能恰好在圆上). 方法:暴力,稍微注意一下精度什么的就好了,1A. 1 #include <bits/stdc++.h>

2016 ICPC 大连网络赛 部分题解

先讲1007,有m个人,n种石头,将n种石头分给m个人,每两个人之间要么是朋友关系,要么是敌人关系,朋友的话他们必须有一种相同颜色的石头,敌人的话他们必须所有石头的颜色都不相同.另外,一个人可以不拥有任何一种石头.求m个人的所有关系是不是都能用n种石头表示出来.比赛当时找的关系是n种石头可以表示n+1个人的关系.但是一直WA,因为考虑不周. 我们考虑这样的一种情况,我们把人分为左边和右边两部分,每边的人里面都互相为敌人,同时左边的任意一个人和右边的任意一个人都是朋友.举个例子,左边有3人,右边两

NOIP模拟 (8-2情人节欢乐赛) 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目来自hzwer的模拟题 果实计数 (count.pas/.c/.cpp) 时间限制:1s,空间限制32MB 题目描述: 淘淘家有棵奇怪的苹果树,这棵树共有n+1层,标号为0~n.这棵树第0层只有一个节点,为根节点.已知这棵树为b叉树,且保证是一颗满b叉树. 现在,该树第n层的每个节点上都结出了一个苹果,淘淘想知道共结了多少苹果.由于数量可能很大,答案要求输出mod k后的结果. 输入描述: 给出第1层的节点数b和层数n和k

2017ACM省赛选拔赛题解

Problem A: 聪明的田鼠 题解: dp[k][i]表示走了k步,且在第i行的最大值 最后的结果就是走了n+m-2步,且在第n行的值 代码: 1 #include <map> 2 #include <set> 3 #include <cmath> 4 #include <queue> 5 #include <stack> 6 #include <cstdio> 7 #include <string> 8 #inclu

哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练. 题解: E666 这个题是让求有多少个子串只含有6.寻找连续的6,然后用n*(n+1)/2求出这一段的子串个数,然后把每一段连续的加起来. 做的时候wa了很多次,原来是在n*(n+1)的地方已经超过int型了,所以需要设置类型为long long. #include <cstdio> #inc

郑轻第六届校赛 -- 部分题解

1427: 数字转换 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 379  Solved: 93 SubmitStatusWeb Board Description 老师交给小明一个任务,有两个数字x和y(x<y),通过以下两种操作:一.将x乘以2:二.将x的值加上1.小明希望能通过尽可能少的操作来完成这个任务,但是不知道怎么做,现在请大家来帮帮他的忙吧. Input 两个整数x,y(0<=x<y<=10^6). Output 一