题解 english
好题 肝完这题感觉头巨痛
首先\(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的更多相关文章
- Java - 收藏集 -
Java - 收藏集 - Java 基础思维导图,让 Java 不再难懂 - 工具资源 - 掘金思维导图的好处 最近看了一些文章的思维导图,发现思维导图真是个强大的工具.了解了思维导图的作用之后, ...
- LeetCode Integer to English Words
原题链接在这里:https://leetcode.com/problems/integer-to-english-words/ Convert a non-negative integer to it ...
- 273. Integer to English Words
题目: Convert a non-negative integer to its english words representation. Given input is guaranteed to ...
- 【Codeforces Round】 #431 (Div. 2) 题解
Codeforces Round #431 (Div. 2) A. Odds and Ends time limit per test 1 second memory limit per test ...
- Codeforces Round #447 (Div. 2) 题解 【ABCDE】
BC都被hack的人生,痛苦. 下面是题解的表演时间: A. QAQ "QAQ" is a word to denote an expression of crying. Imag ...
- LeetCode All in One题解汇总(持续更新中...)
突然很想刷刷题,LeetCode是一个不错的选择,忽略了输入输出,更好的突出了算法,省去了不少时间. dalao们发现了任何错误,或是代码无法通过,或是有更好的解法,或是有任何疑问和建议的话,可以在对 ...
- Codeforces Round #177 (Div. 2) 题解
[前言]咦?如今怎么流行打CF了?于是当一帮大爷在执着的打div 1的时候,我偷偷的在刷div 2.至于怎么决定场次嘛.一般我报一个数字A,随便再拉一个人选一个数字B.然后開始做第A^B场.假设认为机 ...
- 【字符串】【hash】【倍增】洛谷 P3502 [POI2010]CHO-Hamsters 题解
这是一道字符串建模+图论的问题. 题目描述 Byteasar breeds hamsters. Each hamster has a unique name, consisting of lo ...
- Codeforces Round #470 Div. 2题解
A. Protect Sheep time limit per test 1 second memory limit per test 256 megabytes input standard inp ...
随机推荐
- Jmeter监控服务器CPU,Memory,Disk,Network性能指标
本文主要说一下如何通过JMeter插件来监控服务器CPU.内存.磁盘.网络等相关资源. 一.下载 第一种方案: 首先进入网址https://jmeter-plugins.org/downloads/o ...
- 42. Trapping Rain Water [dp][stack]
description: Given n non-negative integers representing an elevation map where the width of each bar ...
- Selenium启动Firefox示例(java版)
本文示例使用selenium启动Firefox,并将浏览器窗口最大化,在百度搜索框内输入"HelloWorld",最后点击搜索按钮. 源代码如下: 1 package com.se ...
- python使用笔记007-内置函数,匿名函数
1.匿名函数 匿名函数也是一个函数,是一个简单的函数,没有名字,只能实现一些简单的功能 1 #匿名函数也是一个函数,是一个简单的函数,没有名字,只能实现一些简单的功能 2 lambda x:x+1#入 ...
- 从零搭建一个IdentityServer——资源与访问控制
IdentityServer作为授权服务器它的最终目的是用于对资源进行管控,这里所说的资源有两种,其一是API资源,实际上也就是OIDC协议中客户端(RP)所需要访问的一系列受保护的资源(API),授 ...
- WIN10 网卡驱动异常代码56的问题及解决方法
故障描述: 原来使用正常的一个微机室,突然一天控制端主机网络连接异常,平时的网络控制软件无法使用.检查网络配置正常,网络诊断.修复.将网卡禁用也没有效果:后来删除网卡想重装,则恶运开始,无法安装驱动: ...
- 跟我一起学Go系列:gRPC 全局数据传输和超时处理
gRPC 在多个 GoRoutine 之间传递数据使用的是 Go SDK 提供的 Context 包.关于 Context 的使用可以看我之前的一篇文章:Context 使用. 但是 Context ...
- 流暢的python學習-3
一.文件操作 #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Created on Thu Apr 23 20:59 ...
- 对一个sql的分析
select * FROM LPEdorItem a, LCCont b, LPEdorApp c WHERE a.edoracceptno = c.edoracceptno and a.ContNo ...
- SQL Server添加字段语法
通用式: alter table [表名] add [字段名] 字段属性 default 缺省值 default 是可选参数增加字段: alter table [表名] add 字段名 smallin ...