传送门

好题 肝完这题感觉头巨痛

首先\(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. 小程序textarea设置maxlength后不是你想的那样简单

    可能很多小伙伴们.看见这个标题后; 觉得作者是一个标题党. textarea设置maxlength后, 限制用户输入的字符呗! 还能怎么样呢? 恭喜你,说对了一半. 之前我也一直是这样想的. 知道今天 ...

  2. SESSION和JWT

    1.传统登录的方式是使用 session + token,比较适用于Web应用的会话管理.token 是指在客户端使用 token 作为用户状态凭证,浏览器一般存储在 localStorage 或者 ...

  3. 从新建文件夹开始构建UtopiaEngine(2)

    本篇序言 摸了两个月的鱼,又一次拾起了自己引擎的框架,开始完善引擎系统,如果非要用现实中的什么东西比喻的话,那么我们目前实现的框架连个脚手架都不是.把这项目这样晾着显然不符合本人的风格,而且要作为毕业 ...

  4. C预处理跨平台

    #include <stdio.h> //不同的平台下引入不同的头文件 #if _WIN32 //识别windows平台 #include <windows.h> #elif ...

  5. 【LeetCode】974. 和可被 K 整除的子数组

    974. 和可被 K 整除的子数组 知识点:数组:前缀和: 题目描述 给定一个整数数组 A,返回其中元素之和可被 K 整除的(连续.非空)子数组的数目. 示例 输入:A = [4,5,0,-2,-3, ...

  6. chcod炸弹

    [题目描述] 话说Cpp国和Pas国发生了战争, Pas国派出了强大的飞机战队, Cpp国于是使出了炸弹CHCOD 来反击Pas国的飞机舰队.然而CHCOD的发射器,只能逐渐往上打.所以Cpp国现在只 ...

  7. 在java中为啥要重写toString 方法?

    在java中为啥要重写toString 方法?下面以一个简单的例子来说明. 先定义一个test5类.并写它的get,set方法. package test5; public class Test5 { ...

  8. IntelliJ IDEA2021.2 常用快捷键汇总总结

    Java开发环境:Windows10 64bit+JDK8+IDEA2021.2 =========================================================== ...

  9. C#曲线分析平台的制作(五,Sqldependency+Signalr+windows 服务 学习资料总结)

    在前篇博客中,利用interval()函数,进行ajax轮询初步的实现的对数据的实时显示.但是在工业级别实时显示中,这并非是一种最好的解决方案.随着Html5 websocket的发展,这种全双工的通 ...

  10. Hyper-V下Internal vSwitch的配置和Linux虚拟机的SSH连接

    最近工作中要在Windows Server 2016/Hyper-V 10中运行Ubuntu16实例,需要制作出"即插即用"的镜像文件,也就是安装好后即可从外部SSH进去.之前我使 ...