【BestCoder #45】

用家里的电脑来编程,各种不算

一开始15分钟刷掉T1和T2,然后就永远地卡在了T3。。。

后来看题解,傻了眼。。。

它强调的“只有一个答案”我还以为这是在提示我二分答案,于是我一直往权值线段树那个方向想去

哪知它还代表一个意思:路径xor值即是答案。。。

好吧我脑袋秀逗了。。

代码:

T1

#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
#define rep(i, l, r) for(int i=l; i<=r; i++)
#define maxn 10009
#define ll long long
using namespace std;
ll read()
{
    ll x=0, f=1; char ch=getchar();
    while (!isdigit(ch)) {if (ch==‘-‘) f=-1; ch=getchar();}
    while (isdigit(ch)) x=x*10+ch-‘0‘, ch=getchar();
    return x*f;
}
ll n;
int main()
{
    int t=read(); while(t--)
    {
        n=read(); int a=0, b=0;
        while (n)
        {
            if (a==0 && (n&1)==1) b++;
            a=n&1; n>>=1;
        }
        printf("%d\n", b);
    }
    return 0;
}

T2

#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
#define rep(i, l, r) for(int i=l; i<=r; i++)
#define maxn 1009
#define maxq 100009
#define lowbit(x) (x&-x)
#define ll long long
using namespace std;
ll read()
{
    ll x=0, f=1; char ch=getchar();
    while (!isdigit(ch)) {if (ch==‘-‘) f=-1; ch=getchar();}
    while (isdigit(ch)) x=x*10+ch-‘0‘, ch=getchar();
    return x*f;
}
struct node{int x,y,z,w;} t[maxq];
int n, q, k[maxn], num[maxn], s[maxn];
bool cmp(node a, node b){return a.x<b.x;};
bool cmp2(node a, node b){return a.w<b.w;};
void Add(int x, int v)
{
    while (x<=n) s[x]+=v, x+=lowbit(x);
}
int Que(int x)
{
    int now=0;
    while (x>0) now+=s[x], x-=lowbit(x);
    return now;
}
int main()
{
    n=read(), q=read();
    rep(i, 1, n) k[i]=read();
    rep(i, 1, q) t[i].x=read(), t[i].y=read(), t[i].w=i; sort(t+1, t+1+q, cmp);
    rep(i, 1, n) rep(j, 1, i-1) if (k[j]>k[i]) num[i]++;
    rep(i, 1, n) Add(i, num[i]);
    int now=1;
    rep(o, 1, q)
    {
        while (now<t[o].x)
        {
            rep(i, now+1, n) if (k[now]>k[i]) Add(i, -1);
            now++;
        }
        t[o].z=Que(t[o].y);
    }
    sort(t+1, t+1+q, cmp2);
    rep(i, 1, q) printf("%d\n", t[i].z);
    return 0;
}

题解:

1001 Dylans loves numbers
这道题就是按照题意模拟。
设读入的数是N,我们先把N分解成二进制形式放在数组A里。(正反顺序没有关系)
然后对A数组循环一边,如果当前位置是1而前一位是0那么计数器就++。注意一些小的细节。
时间复杂度为O(T∗log(N))

1002 Dylans loves sequence
N只有1000,于是想怎么来就怎么来。
最容易想到的是枚举开头,然后Nlog(N)时间里去算逆序对,用一个树状数组维护。
(可惜BC不给卡。。。呜呜呜)
仔细一想发现可以很简单地做到N2.
设ans[l][r]为l∼r的逆序对数量。首先我们暴力地先算好ans[1][1..N]。
然后i从2∼N枚举,每次计算从i开始的逆序对。
那么ans[i][j]比ans[i−1][j]少了什么呢?没错,少了a[i−1]这个数的贡献。
我们再开一个累加器cnt。枚举j从i∼N,如果a[i−1]和a[j]产生逆序对就cnt[j]=−1
然后我们从右往左累加cnt(因为贡献是前缀和性质的)
最后ans[i][j]=ans[i−1][j]+cnt[j]。
预处理完所有的答案就可以O(1)的询问啦。

1003 Dylans loves tree
题目里有一个很神奇的性质:路径上最多只有一个数出现奇数次。
这应该马上想到异或。因为异或两次和没异或是等价的。此外异或满足区间减性质。
因为有修改,我们很自然地想到用数据结构维护。
最无脑的就是直接上树链剖分或是Splay维护区间xor值即可。
仔细想一想,发现可以利用LCA消去“树上路径”,转化为根到x路径上求xor值。
我们可以很经典地直接使用线段树或树状数组维护dfs序。
(然而BC不给我卡log2。。。呜呜呜)
有一个很强的trick就是权值可以为0!
所以比如路径上有3个0,虽然他们xor值还是0,但是他们是出现了奇数次。
我特意把A[i]说成∈自然数集而不是[0,100000],就是想尽量不被发现。
怎么避免呢?单独维护0的情况?
有一个很简单的解决方案:直接把读入时所有权值+1,输出的时候再-1即可!
时间复杂度为O(N∗log(N)2)或者O(N∗log(N))

1004 Dylans loves polynomial
n的范围3000。考虑多项式插值的方法。
因为是对子串进行插值,我们很自然地想到牛顿插值。(如果不会请自行百度)。
那么只需先预处理一个3000∗3000的差商表,然后每次询问就能O(N)的读取对角线上的差商,那么问题就解决了。
时间复杂度为O(N2+NQ)
当然出完题后我还脑补出了一个n^2的拉格朗日的方法。
不过细节有点多,要搞一些前缀积、后缀积来维护,这里不再叙述。

吐槽:验题人说题目有点难,本次出题1002的idea换了好几次,然后基本是1002换成1003,1003换成了1004。(也就是说还有一道有趣的题目未能出出来)
然后大家在Clarification里大量询问C题是否有负和0点权,这给一些同学提了醒~

时间: 2024-10-17 08:59:11

【BestCoder #45】的相关文章

【bestcoder #36】ABCD题解

Strange Class Accepts: 519 Submissions: 1749 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) 问题描述 在Vivid的学校里,有一个奇怪的班级(SC).在SC里,这些学生的名字非常奇怪.他们的名字形式是这样的anbncn(a,b,c两两不相同.).例如,叫"abc","ddppqq"的学生是在SC里的,然而叫&

【bestcoder #35】AB题解

DZY Loves Balls Accepts: 371 Submissions: 988 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) 问题描述 一个盒子里有n个黑球和m个白球.现在DZY每次随机从盒子里取走一个球,取了n+m次后,刚好取完.DZY用这种奇怪的方法生成了一个随机的01串S[1?(n+m)].如果DZY第i次取出的球是黑色的,那么S[i]=1,如果是白色的,那么S[

【BestCoder #44】

因为这场比赛,我愉快地逃掉了晚自修. T1一开始各种SillyB,忘了40%的最低限制... T2各种想吐槽... 明明OJ警告说%lld是不行的我就换成%I64D(上面写这样的)... 结果各种WA 改成%lld然后不顾警告提交 AC... 此时心里:“¥%……#¥……” 后来想了想不是%I64d吗....d是小写的啊.... BC的尿性.... 累觉不爱 T3和T4就都不会做啦... 于是只能A两道,于是100+的排名,于是Rating也上1500了(噗 题解: 1001 ZYB loves

【BestCoder #48】

与之前一样,秒刷A和B,然后就永远卡在了C B也因为少看一句话被Hunt掉了 说说C的做法吧(分块大法好 给定一个序列,每次询问区间l-r,求∑(ai^bi),其中bi是指ai在区间中的出现次数,ai是指有在区间中出现的数. 先把官方的正解贴出来: 然后我用自己的话来说一下.. 分块,首先预处理出h(i,j)和g(a,b),各自的复杂度一个为n^1.5,一个多加上快速幂的logn h的话你可以求出每个块所含有的数 O(块数*块内元素数=n),然后再前缀和累加起来 O(值域*块数=n^1.5) g

【bestcoder #37】ABC题解

Rikka with string Accepts: 395 Submissions: 2281 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) 问题描述 众所周知,萌萌哒六花不擅长数学,所以勇太给了她一些数学问题做练习,其中有一道是这样的: 有一天勇太得到了一个长度为n的字符串,但是六花一不小心把这个字符串搞丢了.于是他们想要复原这一个字符串.勇太记得这个字符串只包含小写字母而且这

【bestcoder #39】CD题解

Code Accepts: 125 Submissions: 736 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) 问题描述 wld有一个长度为n的序列a1..an wld想要你给出下面这段c++代码的输出: int calc() { int res=0; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { res+=gcd(a[i],a[

【BestCoder】#29 C GTY&#39;s gay friends(区间和 随机数判重)

题目大意:可以到相应的场次查看中文翻译. 思路:其实这道题很简单,对于一个等差数列,我们要判断他是否每个数都出现,只需要判断区间和或者是最大值是否符合即可,但这边需要注意的便是中间的重复部分.最大值的判重必要性我就不知道了,而且我也不会做,目测做也超时. 这边就写一下偷别人的区间和+随机数判重的做法 其实这边判重的方法是给一个数加上一个超过1000007的权,然后在计算和的时候,便是唯一的. 否则例如下面的情况 10 11的和可以由5和16构成,既然两个的和可以被另外一个的两个数替代,那我们就找

HDU BestCoder Round #1 1001 逃生 【拓扑排序】

逃生 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 0    Accepted Submission(s): 0 Problem Description 糟糕的事情发生啦,现在大家都忙着逃命.但是逃命的通道很窄,大家只能排成一行. 现在有n个人,从1标号到n.同时有一些奇怪的约束条件,每个都形如:a必须在b之前. 同时,社会是不平等的

剑指Offer:把数组排成最小的数【45】

剑指Offer:把数组排成最小的数[45] 题目描述 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个.例如,输入数组是{3.32.321},则打印出来的这3个数字能拼接成的最小数字是321323. 方法论 简要思路 最暴力的方法是把这个数组中的所有数字的全排列暴力出来,然后找个最小的.但是显然我们不能这么做. 我们应该定义一个排序规则,: 先将整型数组转换成String数组,然后将String数组排序,最后将排好序的字符串数组拼接出来.关键就是制定排序