题解 Cicada 拿衣服
- 见到这些奇奇怪怪的题是不是应该试着证下状态数上界啊
首先观察题目里给的柿子,可以发现 \(or-and\) 单调增, \(min-max\) 单调减
神仙思路,发现对于一个给定的左端点,我怀疑出题人是左撇子,不同的 \(or-and\) 最多只有 \(2logn\) 个,证明应该很简单
那尝试把这些 \(or-and\) 相同的区间拎出来,从右向左枚举区间,在区间内二分可得合法的最远右端点
然后问题来了:如何 \(O(1)\) 维护出这些区间
神仙思路,考虑什么是这些区间的边界,会发现一个数是边界当且仅当这一位上出现了之前没有在这一位上出现过的数
也即比如左边界上第 \(i\) 位是1,那向右找到第一个这一位上是0的数,那个数就会是一个边界
这个可以维护出一个next0和一个next1单调指针,每次排个序处理
然后区间最值,区间与或都需要 \(O(1)\) 出,都可以用ST表
所以满足区间可重性的东西都可以用ST表?
关于区间整体取max:
另一种实现方法是把线段差分,拆分为在 \(l\) 插入一个长度,在 \(r\) 删除一个长度的事件,拿一个multiset
维护,每次取出最大值即可
但这样要求区间数不能太多关于ST表和lca的fa数组:
把大小是log的那一维放在前面真的会快
然后具体实现上注意我让每个端点是区间的右端点,所以每次还得特别把位置 \(n\) 扔进去
Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 1000010
#define ll long long
#define reg register int
#define fir first
#define sec second
#define make make_pair
#define max2(a, b) ((a)>(b)?(a):(b))
#define min2(a, b) ((a)<(b)?(a):(b))
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans;
}
int n, k;
int ta1[28][N], ta2[28][N], ta3[28][N], ta4[28][N], top, lg[N], a[N];
pair<int, int> add[N], del[N];
multiset<int> s;
struct point{
int dlt, pos0, pos1;
point():pos0(1),pos1(1){}
int nxt0(int i) {
//cout<<"nxt0: "<<i<<' '<<pos0<<endl;
if (i>=pos0) {pos0=i+1; i=1<<dlt; while (pos0<=n && (a[pos0]&i)) ++pos0;}
//cout<<"return "<<pos0<<endl;
return pos0;
}
int nxt1(int i) {
if (i>=pos1) {pos1=i+1; i=1<<dlt; while (pos1<=n && !(a[pos1]&i)) ++pos1;}
return pos1;
}
}p[28];
inline int qmin(int l, int r) {
int t=lg[r-l+1]-1;
return min(ta2[t][l], ta2[t][r-(1<<t)+1]);
}
inline int qmax(int l, int r) {
int t=lg[r-l+1]-1;
return max(ta1[t][l], ta1[t][r-(1<<t)+1]);
}
inline int qor(int l, int r) {
int t=lg[r-l+1]-1;
return ta3[t][l]|ta3[t][r-(1<<t)+1];
}
inline int qand(int l, int r) {
int t=lg[r-l+1]-1;
return ta4[t][l]&ta4[t][r-(1<<t)+1];
}
signed main()
{
n=read(); k=read();
for (reg i=1; i<=n; ++i) a[i]=read();
for (reg i=1; i<=n; ++i) ta1[0][i]=ta2[0][i]=ta3[0][i]=ta4[0][i]=a[i];
for (reg i=1; i<=n; ++i) lg[i]=lg[i-1]+(1<<lg[i-1]==i);
int lim=lg[n]-1;
for (reg j=0; j<lim; ++j)
for (reg i=1,t,lm=n-(1<<(j+1))+1; i<=lm; ++i) {
t=i+(1<<j);
ta1[j+1][i]=max2(ta1[j][i], ta1[j][t]);
ta2[j+1][i]=min2(ta2[j][i], ta2[j][t]);
ta3[j+1][i]=ta3[j][i]|ta3[j][t];
ta4[j+1][i]=ta4[j][i]&ta4[j][t];
}
for (reg i=0; i<27; ++i) p[i].dlt=i;
int tem[30];
for (reg i=1; i<=n; ++i) {
//cout<<"i="<<i<<": "<<endl;
for (reg j=0; j<27; ++j) tem[j]=(a[i]&(1<<j))?p[j].nxt0(i):p[j].nxt1(i);
tem[27]=i; tem[28]=n+1;
sort(tem, tem+29);
//assert(tem[0]==i);
//cout<<"tem: "; for (int i=0; i<=27; ++i) cout<<tem[i]<<' '; cout<<endl;
for (reg j=28,t1,t2,l,r,mid; j; --j) {
if (tem[j-1]==tem[j]) continue;
t1=qor(i, tem[j]-1)-qand(i, tem[j]-1), t2=qmin(i, tem[j-1])-qmax(i, tem[j-1]);
if (t1+t2>=k) {
//cout<<"t1="<<t1<<" and t2="<<t2<<' '<<t1+t2<<endl;
//cout<<"tem_j: "<<tem[j-1]<<' '<<tem[j]-1<<endl;
l=tem[j-1], r=tem[j]-1;
while (l<=r) {
mid=(l+r)>>1;
if (t1+qmin(i, mid)-qmax(i, mid)>=k) l=mid+1;
else r=mid-1;
}
//cout<<"lr: "<<l<<' '<<r<<endl;
add[++top]=make(i, l-i), del[top]=make(l, l-i);
break;
}
}
}
sort(del+1, del+top+1);
int pos1=1, pos2=1;
//cout<<"---add---"<<endl; for (int i=1; i<=top; ++i) cout<<add[i].fir<<','<<add[i].sec<<endl;
//cout<<"---del---"<<endl; for (int i=1; i<=top; ++i) cout<<del[i].fir<<','<<del[i].sec<<endl;
for (reg i=1; i<=n; ++i) {
//cout<<"add: "<<add[i].sec<<endl;
while (pos1<=top && add[pos1].fir<=i) s.insert(add[pos1++].sec);
while (pos2<=top && del[pos2].fir<=i) {
//cout<<"del: "<<del[pos].fir<<' '<<del[pos].sec<<endl;
s.erase(s.find(del[pos2++].sec));
}
printf("%d ", s.size()?*s.rbegin():-1);
}
printf("\n");
return 0;
}
题解 Cicada 拿衣服的更多相关文章
- 「10.28」Dove 打扑克(链表)·Cicada 与排序(概率)·Cicada 拿衣服(各种数据结构)
A. Dove 打扑克 考场思考半天线段树树状数组,没有什么想法 打完暴力后突然想到此题用链表实现会很快. 因为只有$n$堆,所以设最多有$x$个不同的堆数,那么$x\times (x-1)/2==n ...
- [CSP-S模拟测试]:Cicada拿衣服(暴力+乱搞)
题目传送门(内部题94) 输入格式 第一行两个整数$n,k$,代表衣服的数量和阈值. 接下来一行$n$个数,第$i$个数$a_i$表示每件衣服的愉悦值. 输出格式 输出一行$n$个数,第$i$个数为$ ...
- NOIP 模拟 $36\; \rm Cicada 拿衣服$
题解 \(by\;zj\varphi\) 发现右端点固定时,左端点的 \(min-max\) 单调递减,且对于 \(or\) 和 \(and\) 相减,最多有 \(\rm2logn\)个不同的值,且相 ...
- 20210811 Dove 打扑克,Cicada 与排序,Cicada 拿衣服
考场 开考感觉 T3 比较可做.T1 看上去不难但毫无思路. 先想了 25min T3,想到一个确定左端点,二分最长的右端点,甚至想到了用猫树维护区间 or and...上厕所回来发现假了,没有单调性 ...
- [考试反思]1028csp-s模拟测试91:预估
这一轮是要闹哪样啊???前十都死活进不去??? 能不能不要到联赛前突然连续掉链子啊!!! 总算难得的切掉了T1.然后又一次把T2和T3的难度估反了 结果给T2剩下了30分钟,想到正解来不及打了. 然后 ...
- Noip模拟36 2021.8.11
刚题的习惯还是改不了,怎么办??? T1 Dove打扑克 考场上打的动态开点线段树+并查集,考后发现自己像一个傻子,并查集就行.. 这几天恶补数据结构疯了 用树状数组维护后缀和,$siz_i$表示编号 ...
- csp-s模拟测试91
csp-s模拟测试91 倒悬吃屎的一套题. $T1$认真(?)分析题意发现复杂度不能带$n$(?),计划直接维护答案,考虑操作对答案的影响,未果.突然发现可以动态开点权值线段树打部分分,后来$Tm$一 ...
- noip模拟36
\(\color{white}{\mathbb{荷花映日,莲叶遮天,名之以:残荷}}\) 今天再次翻车掉出前十 开题看错 \(t1\) 以为操作2的值固定发现是个简单题,然后 \(t2\) 开始大力 ...
- 2021.8.11考试总结[NOIP模拟36]
T1 Dove玩扑克 考场并查集加树状数组加桶期望$65pts$实际$80pts$,考后多开个数组记哪些数出现过,只扫出现过的数就切了.用$set$维护可以把被删没的数去掉,更快. $code:$ 1 ...
随机推荐
- webpack(10)webpack-dev-server搭建本地服务器
前言 当我们使用webpack打包时,发现每次更新了一点代码,都需要重新打包,这样很麻烦,我们希望本地能搭建一个服务器,然后写入新的代码能够自动检测出来,这时候就需要用到webpack-dev-ser ...
- Exception 和Error异常大部分人都犯过的错。
先看再点赞,给自己一点思考的时间,如果对自己有帮助,微信搜索[程序职场]关注这个执着的职场程序员. 我有什么:职场规划指导,技能提升方法,讲不完的职场故事,个人成长经验. 1,简介 Exception ...
- Jenkins集成SonarQube遇到的报错
Jenkins集成Sonar过程中遇到的报错 1.jenkins中无法添加sonarqube的token凭证 因为添加的凭证类型错误,所以无法添加token,类型应该选择"Secret te ...
- VisibleDeprecationWarning , Creating an ndarray from ragged nested sequences... 警告怎么办
我不是完美主义,但是至少,我在做实验的时候不能容忍有 warning 的出现. 今天使用 tensorflow.keras.datasets中的 imdb 数据集,使用 imdb.load_data( ...
- IBM刀箱服务器的SW
刀箱交换机说明: 1.刀箱交换机可以看到的24个口都是ext端口,其中因为授权原因,只激活了前10个端口. 2.交换机配置中的inta端口为服务器直接连接的端口,inta1-inta14,这些都是对应 ...
- servlet核心技术2
一.Servet 与 JDBC 在Servlet中可以使用JDBC技术访问数据库,查询DB数据,然后生成显示页面,接收请求参数,然后对DB操作 为了方便重用和便于维护等目的,经常会采用DAO(Data ...
- NOIP模拟赛T3 斐波那契
1.题目 求 \[\sum_{i=1}^n \sum_{j=1}^m \gcd(F_i,F_j) \] 其中 \(F_k\) 表示斐波那契数列的第 \(k\) 项,对 \(10^9 + 7\) 取模. ...
- python使用笔记11--时间模块
1.时间模块常用方法 1 import time,datetime 2 #格式化好的时间2020-05-16 18:30:52 3 #时间戳1589616753 从unix元年(计算机发明的时间)到现 ...
- 建立属于自己的scrapy crawl模板
本人安装PYTHON3.7安装位置:D:\Python\Python37模板位置:D:\Python\Python37\Lib\site-packages\scrapy\templates\spide ...
- Appium -- adb monkey操作(一)
1.Monkey简介在Android的官方自动化测试领域有一只非常著名的"猴子"叫Monkey,这只"猴子"一旦启动,就会让被测的Android应用程序像猴子一 ...