传送门

好题 肝完这题感觉头巨痛

首先\(n \leqslant 1000\)的部分可以\(n^2\)单调队列,有30pts

然后考场上魔改了下单调栈,让它能顺便维护出以\(1~i-1\)为左端点的区间信息,又拿下op=1的30pts

其实这里第11、12个点的答案必定为0,但是没意识到

至于正解:

其实第一问就跑上面魔改单调栈解法就行,是基于这个性质:

  • \((a\oplus b)*k = \sum\limits_{i=0}^{30} (a\oplus b)*2^i*k\)

    然后就可以按位拆开求解了

    然后第二问利用可持久化trie树实现了查询区间内大于某个数的个数

「模板」可持久化trie树查询区间内大于某个数的个数:

int n, m;
int tot, rot[N], son[N][2], cnt[N];
#define son(a, b) son[a][b]
#define cnt(a) cnt[a]
void ins(int u, int p1, int p2, int dat) {
if (u<0) return ;
int s=bool((1<<u)&dat);
son(p2, s)=++tot;
cnt(son(p2, s))=cnt(son(p1, s))+1;
son(p2, s^1)=son(p1, s^1);
ins(u-1, son(p1, s), son(p2, s), dat);
}
int query(int u, int p1, int p2, int dat) {
//cout<<"query "<<u<<endl;
if (u<0) return 0;
int s=bool((1<<u)&dat), ans=0;
if (!s) ans=query(u-1, son(p1, 0), son(p2, 0), dat)+cnt(son(p2, 1))-cnt(son(p1, 1));
else ans=query(u-1, son(p1, 1), son(p2, 1), dat);
return ans;
} signed main()
{
#ifdef DEBUG
freopen("1.in", "r", stdin);
#endif n=read(); m=read();
for (int i=1; i<=n; ++i) rot[i]=++tot, ins(25, rot[i-1], rot[i], read());
for (int i=1,a,b,c,d; i<=m; ++i) {
a=read(); b=read(); c=read();
cout<<query(25, rot[a-1], rot[b], c)<<endl;
} return 0;
}

但是这题要求区间内数先异或上一个数,再比较大小

其实稍稍改下query函数即可

int n, m;
int tot, rot[N], son[N][2], cnt[N];
#define son(a, b) son[a][b]
#define cnt(a) cnt[a]
void ins(int u, int p1, int p2, int dat) {
if (u<0) return ;
int s=bool((1<<u)&dat);
son(p2, s)=++tot;
cnt(son(p2, s))=cnt(son(p1, s))+1;
son(p2, s^1)=son(p1, s^1);
ins(u-1, son(p1, s), son(p2, s), dat);
}
int query(int u, int p1, int p2, int dat, int dlt) {
//cout<<"query "<<u<<endl;
if (u<0) return 0;
int s=bool((1<<u)&dat), s2=bool((1<<u)&dlt), ans=0;
if (!s2) {
if (!s) ans=query(u-1, son(p1, 0), son(p2, 0), dat, dlt)+cnt(son(p2, 1))-cnt(son(p1, 1));
else ans=query(u-1, son(p1, 1), son(p2, 1), dat, dlt);
return ans;
}
else {
if (!s) ans=query(u-1, son(p1, 1), son(p2, 1), dat, dlt)+cnt(son(p2, 0))-cnt(son(p1, 0));
else ans=query(u-1, son(p1, 0), son(p2, 0), dat, dlt);
return ans;
}
} signed main()
{
#ifdef DEBUG
freopen("1.in", "r", stdin);
#endif n=read(); m=read();
for (int i=1; i<=n; ++i) rot[i]=++tot, ins(25, rot[i-1], rot[i], read());
for (int i=1,a,b,c,d; i<=m; ++i) {
a=read(); b=read(); c=read(); d=read();
cout<<query(25, rot[a-1], rot[b], c, d)<<endl;
} return 0;
}

那有了这个东西,我们考虑原题

要求区间端点异或值大于区间内最大值

那可以分别预处理出每个值所“管辖“的区间,单调栈扫两遍即可,这样不枚举端点而是枚举最大值的话就可以少个\(O(n)\)

有个神仙转化:

每个值所“管辖“的区间至多相互包含,但不能相交

这跟线段树的结构相似,所以区间总长度至多为nlogn

对于每个区间,直接暴力枚举左右区间中较小的一个

树链剖分的折半思想可知,至多枚举log次,枚举的总长度为区间总长度

所以时间复杂度\(O(nlog^2n)\)

Code:

#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long
#define ld long double
#define usd unsigned
#define ull unsigned long long
//#define int long long #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
char buf[1<<21], *p1=buf, *p2=buf;
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
} int n, op;
const ll p=1e9+7;
ll a[N], ans1, ans2; namespace force{
struct que{ll val; int pos; inline void build(ll v_, int p_){val=v_; pos=p_;}}q[N];
void solve() {
ll t;
for (int len=2,l,r; len<=n; ++len) {
l=1; r=0;
for (int i=1; i<=len; ++i) {
while (l<=r && a[i]>=q[r].val) --r;
q[++r].build(a[i], i);
}
for (int i=len,l2; i<=n; ++i) {
l2=i-len+1;
t=a[l2]^a[i];
while (l<=r && q[l].pos<l2) ++l;
while (l<=r && a[i]>=q[r].val) --r;
q[++r].build(a[i], i);
//cout<<"+= "<<t*q[l].val<<endl;
ans1 = (ans1+t*q[l].val)%p;
ans2 = (ans2+((t>q[l].val)?q[l].val:0))%p;
}
}
if (op==1) printf("%lld\n", ans1%p);
else if (op==2) printf("%lld\n", ans2%p);
else printf("%lld\n%lld\n", ans1%p, ans2%p);
exit(0);
}
} namespace task1{
struct que2{
struct que{ll val, cnt, sum; inline void build(ll v_, ll p_, ll s_){val=v_; cnt=p_; sum=s_;}}q[N];
int l, r;
que2():l(1),r(0){}
void upd(ll w) {
if (l>r || w<q[r].val) return ;
ll cnt=0;
while (l<=r && w>=q[r].val) cnt+=q[r--].cnt;
ll s=(l<=r)?q[r].sum:0;
q[++r].build(w, cnt, (s+w*(cnt)%p)%p);
}
void add(ll w) {
ll cnt=0;
while (l<=r && w>=q[r].val) cnt+=q[r--].cnt;
ll s=(l<=r)?q[r].sum:0;
q[++r].build(w, cnt+1, (s+w*(cnt+1)%p)%p);
}
ll ask(ll w) {return l<=r?q[r].sum:0;}
}que[22][2];
void solve() {
for (int i=1; i<=n; ++i) {
for (int j=0; j<22; ++j) {
int s=(a[i]&(1<<j))?1:0;
que[j][s^1].upd(a[i]);
ans1=(ans1+(que[j][s^1].ask(a[i]))*(1<<j)%p)%p;
que[j][s].add(a[i]);
}
}
printf("%lld\n", ans1%p);
}
} namespace task2{
int l[N], r[N];
struct que{ll val; int pos; inline void build(ll v_, int p_){val=v_; pos=p_;}}q[N];
int ql, qr; const int SIZE=N*50;
int tot, rot[N], son[SIZE][2], cnt[SIZE];
#define son(a, b) son[a][b]
#define cnt(a) cnt[a]
void ins(int u, int p1, int p2, int dat) {
if (u<0) return ;
int s=bool((1<<u)&dat);
son(p2, s)=++tot;
cnt(son(p2, s))=cnt(son(p1, s))+1;
son(p2, s^1)=son(p1, s^1);
ins(u-1, son(p1, s), son(p2, s), dat);
//if (u>1) pushup(p2);
}
int query(int u, int p1, int p2, int dat, int dlt) {
//cout<<"query "<<u<<endl;
if (u<0) return 0;
int s=bool((1<<u)&dat), s2=bool((1<<u)&dlt), ans=0;
if (!s2) {
if (!s) ans=query(u-1, son(p1, 0), son(p2, 0), dat, dlt)+cnt(son(p2, 1))-cnt(son(p1, 1));
else ans=query(u-1, son(p1, 1), son(p2, 1), dat, dlt);
return ans;
}
else {
if (!s) ans=query(u-1, son(p1, 1), son(p2, 1), dat, dlt)+cnt(son(p2, 0))-cnt(son(p1, 0));
else ans=query(u-1, son(p1, 0), son(p2, 0), dat, dlt);
return ans;
}
} void solve() {
ql=qr=1; q[1].build(INF, 0);
for (int i=1; i<=n; ++i) {
while (ql<=qr && q[qr].val<a[i]) --qr;
l[i]=q[qr].pos+1;
q[++qr].build(a[i], i);
}
ql=qr=1; q[1].build(INF, n+1);
for (int i=n; i; --i) {
while (ql<=qr && q[qr].val<=a[i]) --qr;
r[i]=q[qr].pos-1;
q[++qr].build(a[i], i);
}
//cout<<"l: "; for (int i=1; i<=n; ++i) cout<<l[i]<<' '; cout<<endl;
//cout<<"r: "; for (int i=1; i<=n; ++i) cout<<r[i]<<' '; cout<<endl;
for (int i=1; i<=n; ++i) rot[i]=++tot, ins(21, rot[i-1], rot[i], a[i]);
for (int i=1; i<=n; ++i) {
if (l[i]==r[i]) continue;
if (i-l[i]<r[i]-i) for (int j=l[i]; j<=i; ++j) ans2=(ans2+a[i]*query(21, rot[i-1], rot[r[i]], a[i], a[j])%p)%p; //, cout<<"query "<<i<<' '<<r[i]<<' '<<j<<endl;
else for (int j=i; j<=r[i]; ++j) ans2=(ans2+a[i]*query(21, rot[l[i]-1], rot[i], a[i], a[j])%p)%p; //, cout<<"query "<<l[i]<<' '<<i<<' '<<j<<endl;
}
printf("%lld\n", ans2%p);
}
} signed main()
{
#ifdef DEBUG
freopen("1.in", "r", stdin);
#endif n=read(); op=read();
for (int i=1; i<=n; ++i) a[i]=read();
if (op==1||op==3) task1::solve();
if (op==2||op==3) task2::solve(); return 0;
}

题解 english的更多相关文章

  1. Java - 收藏集 -

    Java - 收藏集 -   Java 基础思维导图,让 Java 不再难懂 - 工具资源 - 掘金思维导图的好处 最近看了一些文章的思维导图,发现思维导图真是个强大的工具.了解了思维导图的作用之后, ...

  2. LeetCode Integer to English Words

    原题链接在这里:https://leetcode.com/problems/integer-to-english-words/ Convert a non-negative integer to it ...

  3. 273. Integer to English Words

    题目: Convert a non-negative integer to its english words representation. Given input is guaranteed to ...

  4. 【Codeforces Round】 #431 (Div. 2) 题解

    Codeforces Round #431 (Div. 2)  A. Odds and Ends time limit per test 1 second memory limit per test ...

  5. Codeforces Round #447 (Div. 2) 题解 【ABCDE】

    BC都被hack的人生,痛苦. 下面是题解的表演时间: A. QAQ "QAQ" is a word to denote an expression of crying. Imag ...

  6. LeetCode All in One题解汇总(持续更新中...)

    突然很想刷刷题,LeetCode是一个不错的选择,忽略了输入输出,更好的突出了算法,省去了不少时间. dalao们发现了任何错误,或是代码无法通过,或是有更好的解法,或是有任何疑问和建议的话,可以在对 ...

  7. Codeforces Round #177 (Div. 2) 题解

    [前言]咦?如今怎么流行打CF了?于是当一帮大爷在执着的打div 1的时候,我偷偷的在刷div 2.至于怎么决定场次嘛.一般我报一个数字A,随便再拉一个人选一个数字B.然后開始做第A^B场.假设认为机 ...

  8. 【字符串】【hash】【倍增】洛谷 P3502 [POI2010]CHO-Hamsters 题解

        这是一道字符串建模+图论的问题. 题目描述 Byteasar breeds hamsters. Each hamster has a unique name, consisting of lo ...

  9. Codeforces Round #470 Div. 2题解

    A. Protect Sheep time limit per test 1 second memory limit per test 256 megabytes input standard inp ...

随机推荐

  1. python 16篇 多线程和多进程

    1.概念 线程.进程 进程 一个程序,它是一组资源的集合 一个进程里面默认是有一个线程的,主线程 多进程是可以利用多核cpu的线程 最小的执行单位 线程和线程之间是互相独立的 主线程等待子线程执行结束 ...

  2. 关于hive的基础

    Hive基础 1.引入原因 对存在HDFS上的文件或HBase中的表进行查询时,是要手工写一堆MapReduce代码 对于统计任务,只能由懂MapReduce的程序员才能搞定 事实上,许多底层细节实际 ...

  3. [刘阳Java]_Spring AOP注解详细介绍_第8讲

    这节内容非常关键,我们会比较详细地介绍Spring AOP注解的使用 1. 要使用Spring AOP注解,必须满足如下的事项 导入Aspectj的jar.Spring3.0-AOP.jar.aopa ...

  4. IO流 connect reset

    目录 出现场景 解决思路 出现场景 通过外部OBS下载10文件,然后通过工具将这10个文件打包成一个文件A.zip上传,最后将这个A.zip下载并解压,解压A.zip后发现文件数量不是10个. 解决思 ...

  5. React组件三大属性之 refs

    React组件三大属性之 refs refs属性 1) 组件内的标签都可以定义ref属性来标识自己 a. <input type="text" ref={input => ...

  6. 微信小程序云开发-云存储-下载并打开文件文件(word/excel/ppt/pdf)

    一.wxml文件 1.写文本框,用来获取文件链接. 2.按钮,点击下载文件 <!-- 下载文件(word/excel/ppt/pdf等) --> <view class=" ...

  7. 记一次系统崩溃事件【Mac版】

    事件:Mac系统崩溃,导致电脑数据丢失,以及数据安全备份措施的不到位的教训! 解决措施: 1.开机后按:Command+R 按开机键 ,进入Mac 实用工具, 选择磁盘工具.由于没有备份直接抹掉磁盘. ...

  8. 第三十二篇 -- CreateFile、ReadFile、WriteFile

    一.CreateFile 这是一个多功能的函数,可打开或创建文件或者I/O设备,并返回可访问的句柄:控制台,通信资源,目录(只读打开),磁盘驱动器,文件,邮槽,管道. 函数原型: HANDLE WIN ...

  9. 【阅读笔记】Java核心技术卷一 #4.Chapter6

    6 接口.lambda 表达式与内部类 6.1 接口 6.1.1 接口概念 接口绝不能含有实例域:但在接口中可以定义常量,被自动设为 public static final 接口中的所有方法自动地属于 ...

  10. 【阿菜用工具】利用 Web3.js 在 ganache 上部署以及调用智能合约

    合约部署 要部署的合约 pragma solidity ^0.4.23; contract test { uint256 value; function setValue(uint256 _value ...