Educational Codeforces Round 65 E,F
E. Range Deleting
题意:给出一个序列,定义一个操作f(x,y)为删除序列中所有在[x,y]区间内的数。问能使剩下的数单调不减的操作f(x,y)的方案数是多少。
解法:不会做,思维跟不上,双指针也不熟练。思路和代码都是学习https://edwiv.com/archives/587这位巨佬的。
说下我的理解:我们考虑怎样的操作[l,r]才是合理的?很容易能想到有3个条件:①删除后剩下的数字[1,l-1]的位置是单调递增,②数字[r+1,x]的位置也是单调递增的,3 数字l-1的所有位置都要比r+1小。那么我们的任务就是预处理这个序列使得能快速判断这3个条件。
posmin[maxn] posmax[maxn]
表示每个数下标的最小值和最大值
premax[maxn] sufmin[maxn]
表示[1,i]/[i,x]范围内的数出现的下标值的最大值/最小值
precan[maxn] sufcan[maxn]
表示[1,i]是否合法,[i,x]是否合法
然后判断[l,r]是否是一个合理操作的条件就是:precan[l-1] && sufcan[r+1] && (premax[l-1]<sufmin[r+1]); //这分别对应上面的3个条件
那么到这里我们就能够O(1)快速判断某个操作是否合法,接下来就是统计答案。当然不能n^2统计会超时,这里用到双指针的技巧,枚举左端点l,右端点r由上一个左端点l-1的r继承而来,之后再实际判断移动得到当前左端点l的应该右端点r,就可以统计答案贡献就是x-r+1咯。这里的正确性是基于:[l,r]是合理的那么l+1的r必定大于l的r,左右端点是同步递增的。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e6+;
int n,x,a[N];
int posmin[N],posmax[N],premax[N],sufmin[N];
bool precan[N],sufcan[N]; bool check(int l,int r) { //判断删去区间[l,r]后是否得到合理答案
return precan[l-] && sufcan[r+] && (premax[l-]<sufmin[r+]);
} int main()
{
cin>>n>>x;
memset(posmin,0x3f,sizeof(posmin));
memset(posmax,,sizeof(posmax));
for (int i=;i<=n;i++) {
scanf("%d",&a[i]);
posmin[a[i]]=min(posmin[a[i]],i);
posmax[a[i]]=max(posmax[a[i]],i);
}
for (int i=;i<=x;i++) premax[i]=max(premax[i-],posmax[i]);
sufmin[x+]=n+; for (int i=x;i;i--) sufmin[i]=min(sufmin[i+],posmin[i]);
memset(precan,,sizeof(precan)); precan[]=;
for (int i=;i<=x;i++) precan[i]=precan[i-]&&(posmin[i]>premax[i-]);
memset(sufcan,,sizeof(sufcan)); sufcan[x+]=;
for (int i=x;i;i--) sufcan[i]=sufcan[i+]&&(posmax[i]<sufmin[i+]); LL ans=;
int l=,r=; //双指针
for (;l<=x;l++) { //左指针遍历
if (l>r) r=l;
while (r<x && !check(l,r)) r++; //移动右指针
if (check(l,r)) ans+=(x-r+); //累加左指针为l时候的贡献为(x-r+1)
}
cout<<ans<<endl;
return ;
}
F. Scalar Queries
解法:虽然能猜到是算排名贡献乘以数字得到答案,但是还是没做出来qwq。参考https://www.cnblogs.com/carcar/p/10877964.html这位巨佬的。
讲一下自己的理解:容易发现其实答案就是算d[i]*a[i]。这个d[i]系数其实就是所有包含a[i]这个数的区间的a[i]的排名总和。那么怎么样才能快速算得这个d[i]?我们从贡献这个角度思考:
在a[i]的左边,只有a[j]<a[i](j<i)的时候a[j]对a[i]才会有提升排名的作用,并且这个提升一个排名的效果在所有包含了(a[j]和a[i])的区间都有效。
同理的,在a[i]的右边,只有a[j]<a[i](j<i)的时候才有提升排名的作用,并且在所有包含a[j]和a[i]的区间有效。
然后对于a[i]自己也是同理,自己给自己提升了一个排名。
那么我们怎么快速算 a[j]<a[i] 且所有包含了a[j] a[i]的区间个数呢?以a[i]左边为例分析,仔细观察发现其实区间个数就是j*(n-i+1),对于每个a[j]这个因子j是不会改变的,然后对于a[i]这个因子(n-i+1)也是不会改变的。我们要做的就是快速统计所有a[j]<a[i]的因子j的总和,嗯?这不就是树状数组。对,我们从左到右扫一遍利用树状数组统计,从右往左扫一遍,统计得出d[i]之后此题就解决了。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=5e5+;
const int P=1e9+;
int n,m,a[N],b[N],rk[N];
LL d[N]; LL sum[N];
void update(int x,int v) {
for (;x<=n;x+=x&-x) sum[x]+=v,sum[x]%=P;
}
LL query(int x) {
LL ret=;
for (;x;x-=x&-x) ret+=sum[x],ret%=P;
return ret;
} int main()
{
cin>>n;
for (int i=;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
sort(b+,b+n+);
for (int i=;i<=n;i++) rk[i]=lower_bound(b+,b+n+,a[i])-b; for (int i=;i<=n;i++) { //计算[1,i-1]区间的贡献
d[i]=(d[i]+query(rk[i]-)*(n-i+)%P)%P;
update(rk[i],i);
}
for (int i=;i<=n;i++) d[i]=(d[i]+(LL)i*(n-i+)%P)%P; //计算[i,i]的贡献
memset(sum,,sizeof(sum));
for (int i=n;i;i--) { //计算[i+1,n]的贡献
d[i]=(d[i]+query(rk[i]-)*(i)%P)%P;
update(rk[i],n-i+);
} LL ans=;
for (int i=;i<=n;i++) ans=(ans+a[i]*d[i]%P)%P;
cout<<ans<<endl;
return ;
}
Educational Codeforces Round 65 E,F的更多相关文章
- Educational Codeforces Round 65 (Rated for Div. 2)题解
Educational Codeforces Round 65 (Rated for Div. 2)题解 题目链接 A. Telephone Number 水题,代码如下: Code #include ...
- codeforces Educational Codeforces Round 24 (A~F)
题目链接:http://codeforces.com/contest/818 A. Diplomas and Certificates 题解:水题 #include <iostream> ...
- Educational Codeforces Round 65 (Rated for Div. 2) D. Bicolored RBS
链接:https://codeforces.com/contest/1167/problem/D 题意: A string is called bracket sequence if it does ...
- Educational Codeforces Round 65 (Rated for Div. 2) C. News Distribution
链接:https://codeforces.com/contest/1167/problem/C 题意: In some social network, there are nn users comm ...
- Educational Codeforces Round 65 (Rated for Div. 2) B. Lost Numbers
链接:https://codeforces.com/contest/1167/problem/B 题意: This is an interactive problem. Remember to flu ...
- Educational Codeforces Round 65 (Rated for Div. 2) A. Telephone Number
链接:https://codeforces.com/contest/1167/problem/A 题意: A telephone number is a sequence of exactly 11 ...
- Educational Codeforces Round 65 (Div. 2)
A.前n-10个有8即合法. #include<cstdio> #include<cstring> #include<iostream> #include<a ...
- [ Educational Codeforces Round 65 (Rated for Div. 2)][二分]
https://codeforc.es/contest/1167/problem/E E. Range Deleting time limit per test 2 seconds memory li ...
- Educational Codeforces Round 65 (Rated for Div. 2)
A:签到. #include<bits/stdc++.h> using namespace std; #define ll long long #define inf 1000000010 ...
随机推荐
- mongdb 副本集的原理、搭建、应用
在了解了这篇文章之后,可以进行该篇文章的说明和测试.MongoDB 副本集(Replica Set)是有自动故障恢复功能的主从集群,有一个Primary节点和一个或多个Secondary节点组成.类似 ...
- spark 计算结果写入mysql 案例及常见问题解决
package com.jxd import org.apache.spark.SparkContextimport org.apache.spark.SparkConfimport java.sql ...
- Did you mean to run dotnet SDK commands
把所有的net core的sdk,runtime,hosting通通卸载重新安装了2.1.1版本,发现再运行dotnet命令就是下面信息: C:\Users\Administrator>dotn ...
- Session过期,如何跳出iframe框架页的问题
跳出框架页,实际上是更改父页面地址.那么更改父页面地址很简单即: window.parent.location='/Login/loginindex'; 这里说session过期,那么浏览器端的任何请 ...
- Linux 统计文件夹下文件个数及目录个数
1. 统计文件夹下文件的个数 ls -l | grep "^-" | wc -l 2.统计文件夹下目录的个数 ls -l | grep "^d" | wc -l ...
- web项目问题总结
1.项目编码问题:建立项目之初,应统一设置项目组所有电脑的eclipse 默认项目编码,还有各个文件的编码格式 中文乱码的问题,需要三个地方同时设置utf-8编码,第一是数据库里表的编码,第二是jsp ...
- 为你的AliOS Things应用增加自定义cli命令
摘要: 怎么才能在RTOS系统中,通过 串口shell控制LED的开关. 在日常嵌入式开发中,我们经常会用串口命令来使设备进入某种特定的状态,或执行某个特定的操作.如系统自检,模拟运行,或者进入手动模 ...
- php strncasecmp()函数 语法
php strncasecmp()函数 语法 作用:比较字符串前n个字符,不区分大小写直线电机 语法:strncasecmp(string1,string2,length) 参数: 参数 描述 str ...
- Docker(应用服务引擎)
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱机制,相互之间不会有任何 ...
- LUOGU P4088 [USACO18FEB]Slingshot(线段树)
传送门 解题思路 推了推式子发现是个二维数点,想了想似乎排序加线段树难写,就写了个树套树,结果写完看见空间才\(128M\)..各种奇技淫巧卡空间还是\(MLE\)到天上.后来只好乖乖的写排序+线段树 ...