题目大意:

给定一个数列$a$,有以下几种询问:

1. 给定$x$,在序列末尾插入$x$。
2. 给定$l,r$,输出$\sum\limits_{i=l}^r a_i$。
3. 给定$x$,将数列中的所有数异或$x$。
4. 将当前数列从小到大排序。

解题思路:

考虑某一时刻数列的状态,一定是前面一段有序,后面一段无序。

首先考虑第三个操作,显然用一个变量记一下全局异或的值$X$就可以了。对于第一个操作,先把$x$异或上$X$再插入。

计算贡献的话,可以按位考虑,记录一下这一位有多少个即可。

如果没有排序操作,直接记一下每一位的前缀和即可。

考虑排序操作,前面有序的我们不去动它,后面无序的,直接把它插在正确的位置即可。显然一个数只会被插入一次。用01Trie或线段树维护一下区间各个位的出现次数即可做到区间查询(可以用前缀相减来搞)。

然而操作3会改变已经排完序的数的大小关系。我们考虑一下性质。

考虑最高位,如果它异或上了1,则这个序列的后一部分(最高位为1的那些数)会整体变到前面来。而每个部分内部的相对顺序不变。然后对每一部分,再对次高位考虑。依次类推。

对应到数据结构内部,我们发现,如果某一位异或上了1,相当于这一层的节点的左右儿子交换了一下。

我们不需要真的交换,只需要在询问的时候判断一下往哪边走即可。

这样就非常简单了,代码也很好写。

时间复杂度$O(n\log^2 A)$。

C++ Code:

#include<iostream>
#include<cstring>
const int N=2e5+5;
typedef long long LL;
int n,p,a[N],pre[N][31],A,m,cnt=1,ch[N<<4][2],wg[N<<4][31],sz[N<<4];
int STD;
inline void insert(const int&X){
int u=1;
for(int i=30;~i;--i){
++sz[u];
for(int j=0;j<31;++j)
wg[u][j]+=X>>j&1;
const int sn=X>>i&1;
if(!ch[u][sn])ch[u][sn]=++cnt;
u=ch[u][sn];
}
++sz[u];
for(int j=0;j<31;++j)
wg[u][j]+=X>>j&1;
}
LL query(int k){
LL ret=0;
int val=0;
int u=1;
for(int i=30;~i;--i){
const int _0=STD>>i&1;
if(sz[ch[u][_0]]>=k)u=ch[u][_0],val|=_0<<i;else{
int x=sz[ch[u][_0]];
k-=x;
for(int j=0;j<31;++j){
int cnt=wg[ch[u][_0]][j];
if(A>>j&1)cnt=x-cnt;
ret+=(LL)cnt<<j;
}
u=ch[u][!_0];
val|=!_0<<i;
}
}
val^=A;
return ret+(LL)val*k;
}
inline LL calc(int l,int r){
const int len=r-l+1;
LL ret=0;
for(int i=0;i<31;++i){
int cnt=pre[r][i]-pre[l-1][i];
if(A>>i&1)cnt=len-cnt;
ret+=(LL)cnt<<i;
}
return ret;
}
inline LL solve(int l,int r){return query(r)-query(l-1);}
int main(){
std::ios::sync_with_stdio(0),std::cin.tie(0),std::cout.tie(0);
std::cin>>n;p=1;
for(int i=1;i<=n;++i){
std::cin>>a[i];
for(int j=0;j<31;++j)
pre[i][j]=pre[i-1][j]+(a[i]>>j&1);
}
std::cin>>m;
while(m--){
int op;
std::cin>>op;
switch(op){
case 1:{
int x;
std::cin>>x;
x^=A;
a[++n]=x;
for(int i=0;i<31;++i)
pre[n][i]=pre[n-1][i]+(a[n]>>i&1);
break;
}
case 2:{
int l,r;
std::cin>>l>>r;
LL ans;
if(r<p)ans=solve(l,r);else
if(l>=p)ans=calc(l,r);else
ans=solve(l,p-1)+calc(p,r);
std::cout<<ans<<'\n';
break;
}
case 3:{
int x;
std::cin>>x;
A^=x;
break;
}
case 4:{
for(int i=p;i<=n;++i)
insert(a[i]);
STD=A;
p=n+1;
memset(pre[n],0,sizeof*pre);
break;
}
}
}
return 0;
}

[Ynoi2011]D2T1的更多相关文章

  1. P5312 [Ynoi2011]D2T1

    思路:01trie 按位维护 提交:5边 错因:爆int + 少处理询问时的右端点 题解: 见代码(已经不想说什么了) 代码 //I have my own flg; #include<bits ...

  2. 【二分查找】 跳石头NOIP2015提高组 D2T1

    [二分查找]跳石头NOIP2015提高组 D2T1 >>>>题目 [题目描述] 一年一度的“跳石头”比赛又要开始了! 这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石 ...

  3. [NOIP2018 TG D2T1]旅行

    题目大意:$NOIP\;TG\;D2T1$ 题解:一棵树的很简单,第一个点一定是$1$,只需要对每个节点,找最小的没有访问过的节点访问即可,我写的是$O(n\log_2n)$. 考虑基环树的部分,一个 ...

  4. noip 2018 d2t1 旅行

    noip 2018 d2t1 旅行 (题目来自洛谷) 给定n个城市,m条双向道路的图, 不存在两条连接同一对城市的道路,也不存在一条连接一个城市和它本身的道路.并且, 从任意一个城市出发,通过这些道路 ...

  5. 嵊州D2T1 “我只是来打个电话”

    嵊州D2T1 “我只是来打个电话” 精神病院有一个这样的测试. 给出一个正整数集合,集合中的数各不相同,然后要求病人回答: 其中有多少个数,恰好等于集合中另外两个(不同的)数之和? 回答正确的人,即可 ...

  6. 【NOIP/CSP2019】D2T1 Emiya 家今天的饭

    这个D2T1有点难度啊 原题: 花了我一下午的时间,作为D2T1的确反常 条件很奇怪,感觉不太直观,于是看数据范围先写了个暴力 写暴力的时候我就注意到了之前没有仔细想过的点,烹饪方式必须不同 虽然a很 ...

  7. P5311 [Ynoi2011] 成都七中

    P5311 [Ynoi2011] 成都七中 题意 给你一棵 \(n\) 个节点的树,每个节点有一种颜色,有 \(m\) 次查询操作. 查询操作给定参数 \(l\ r\ x\),需输出: 将树中编号在 ...

  8. 从 洛谷P5309 Ynoi2011 初始化 看卡常

    一般情况下,程序运行消耗时间主要与时间复杂度有关,超时与否取决于算法是否正确. 但对于某些题目,时间复杂度正确的程序也无法通过,这时我们就需要卡常数,即通过优化一些操作的常数因子减少时间消耗. 比如这 ...

  9. noip 2016提高组D2T1 problem

    我们可以先预处理一下组合数模K的值,然后我们可以发现对于答案ji[n][m],可以发现递推式ji[i][j]=ji[i-1][j]+ji[i][j-1]-ji[i-1][j-1]并对于Cij是否%k等 ...

随机推荐

  1. POJ 3311

    设dp状态为dp[i][j]为当前访问过的结点状态为i且当前停留点为j时的最短路径.用二进制存存储访问过的状态,访问过为1,否则为0. #include <iostream> #inclu ...

  2. object-c 不定參数的遍历和原理

    object-c接收随意类型的參数: /** * 接收String类型的多个參数 * @param firsParam 第一个參数 */ -(void)TestString:(NSString*)fi ...

  3. String字符串方法具体解释

    Java开发中,基本都会用户String,有些时候忘记了它还有某一个方法,或者曾经没有使用到.而这些方法可能会节约非常多时间.自己为了学习这些方法,决定对部分測试一下. 定义:String=" ...

  4. 严格符合CommonJS规范的包特性

    严格符合CommonJS规范的包应该具备下面特性: 1.package.json必须在包的顶层文件夹下. 2.二进制文件应该在bin文件夹下. 3.JavaScript代码应该在lib文件夹下. 4. ...

  5. 对扩展openflow协议的一点思考

         软件定义X变得越来越火,正所谓,Software is eating the world. 软件定义网络也是如此.不论是在工业界还是学术界都将是一次伟大的革命,都在紧随着这个行业的方向,找自 ...

  6. Unix网络编程 高级IO套接字设置超时

    我们知道.对于一个套接字的读写(read/write)操作默认是堵塞的.假设当前套接字还不可读/写,那么这个操作会一直堵塞下去,这样对于一个须要高性能的server来说,是不能接受的.所以,我们能够在 ...

  7. linux select函数:Linux下select函数的使用详解【转】

    本文转载自;http://www.bkjia.com/article/28216.html Linux下select函数的使用 Linux下select函数的使用 一.Select 函数详细介绍 Se ...

  8. EOJ 3194 字符串消除

    给定一个由大写字母’A’.’B’.’C’构成的字符串s,按如下进行消除过程: 1.字符串s中连续相同字母组成的子串,如果子串的长度大于1,那么这些子串会被同时消除,余下的字符拼成新的字符串. 例如:” ...

  9. Python中的math和保留小数位数方法

    转载自 http://xukaizijian.blog.163.com/blog/static/17043311920111163272414/ math模块实现了许多对浮点数的数学运算函数.  这些 ...

  10. PCB MS SQL表值函数与CLR 表值函数 (例:字符串分割转表)

    将字符串分割为表表经常用到,这里 SQL表值函数与CLR  表值函数,两种实现方法例出来如下: SELECT * FROM FP_EMSDB_PUB.dbo.SqlSplit('/','1oz/1.5 ...