题解 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 ...
随机推荐
- Leetcode No.53 Maximum Subarray(c++实现)
1. 题目 1.1 英文题目 Given an integer array nums, find the contiguous subarray (containing at least one nu ...
- VS2017编译动态链接库报错
编译后加载DLL,但却无法找到函数入口 经过排查 ,发现问题如下: 加extern "C"的作用是强制该输出函数的名称保留C语言的命名方式.这是因为,如果不强制的话,VC就将你的函 ...
- 详解Spring中Bean的作用域与生命周期
摘要:在利用Spring进行IOC配置时,关于bean的配置和使用一直都是比较重要的一部分,同时如何合理的使用和创建bean对象,也是小伙伴们在学习和使用Spring时需要注意的部分,所以这一篇文章我 ...
- Django基础009--Paginator分页
1.引入 from django.core.paginator import Paginator 2.Paginator对象提供的方法 articles = models.Article.object ...
- [刘阳Java]_CSS鼠标悬停
小白在学习前端技术时候,一定会在刚开始的时候学习CSS2和CSS3的相关知识.这篇内容给大家介绍一个CSS鼠标悬停的效果.大家可以先看下面的效果图,然后我们在说一下实现的效果要求吧 上图效果非常简单和 ...
- ubuntu18.04安装redis-desktop-manager
通过proxychains4 clone项目,否则安装不成功 教程:https://www.cnblogs.com/bignode/p/9254500.html 1 git clone --recur ...
- STEVE JOBS: Stanford Commencement【Stay Hungry. Stay Foolish.】
In 2005, a year after he was first diagnosed with cancer, Apple CEO Steve Jobs made a candid speech ...
- Deepin 20.1打造软件开发环境
支持国产操作系统,替代Windows势在必行,不能让美国卡"脖子"是广大计算机爱好者的共同心愿,下面列举一下Deepin V20.1下如何安装常用软件 ============== ...
- 深入刨析tomcat 之---第1篇,解决第1,2章bug 页面不显示内容Hello. Roses are red.
writedby 张艳涛, 第一个问题是不显示index.html网页 19年才开始学java的第二个月,就开始第一遍看这本书,我估计当初,做第一章的一个案例,自己写代码,和验证就得一天吧,当初就发现 ...
- Oracle 分页查询的一个实例
1.分页模板 select * from ( select rownum as rn , a.* from( 某个表名) a) where rn between 0 and 6 2 某个表名 sele ...