[JZOJ NOIP2018模拟10.21]
考试之前我刚刚领略到了特判的重要性,没想到T2的两个子任务还是写挂了,丢了20分
考试的感觉不行,一路打的都是暴力,正解的思路想到一半就断了推不下去
T1:逛公园
题目链接:
https://jzoj.net/senior/#contest/show/2534/0
题目:
琥珀色黄昏像糖在很美的远方,思念跟影子在傍晚一起被拉长……
小 B 带着 GF 去逛公园,公园一共有 n 个景点,标号为 1 . . . n。景点之间有 m 条路径相连。
小 B 想选择编号在一段区间 [l, r] 内的景点来游玩,但是如果这些景点的诱导子图形成了环,那么 GF 将会不高兴。
小 B 给出很多个询问 [x, y],想让你求有多少个区间 [l, r] 满足 x ≤ l, r ≤ y 且不会使 GF不高兴。
题解:
先来一遍tarjan把所有的点双拿出来,这张图就是环了。发现我们只需要知道环上节点编号的最大值和最小值就能判断当前区间是否包含这个环,问题转化为数轴上有一堆线段,每次询问一个区间不包含任何一条线段的方案数
我们设$lf$数组表示当前点能向左延伸的最远处,注意这个数组显然是单调增的,这个可以预处理出来。怎么预处理呢?对于每条线段$[l,r]$,我们令$lf[r]=l+1$,然后从左到右$lf[1]=1$,$lf[i]=max(lf[i],lf[i-1])(i>2)$
这样我们对于一组询问就可以统计答案了。若当前询问区间为$[x,y]$,假设其中的一个位置$i$,若满足$lf[i]>=x$,那么它对答案的贡献就是$i-lf[i]+1$;若满足$lf[i]<x$,那么对答案的贡献就是$i-x+1$
由于lf数组具有单调性,我们可以二分出一个位置i满足$lf[i]>=x,lf[i-1]<x$,对于$[i,y]$我们显然可以通过前缀和优化$O(1)$查询,对于$[x,i-1]$我们发现是一个等差数列,贡献是$\frac{(i-x+1)\times(i-x)}{2}$
当然若是二分出来的$i$大于$y$,那么$[x,y]$的任意一个区间都是合法的,这个需要特判一下
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<iostream>
#include<vector>
using namespace std;
typedef long long ll; const int N=3e5+;
const int inf=1e9;
int n,m,tot=,tp,tim,cnt;
int head[N],dfn[N],low[N],sta[N],lf[N];
ll rsum[N];
struct EDGE{
int to,nxt;
}edge[N<<];
struct node{
int mx,mi;
}vd[N];
inline int read(){
char ch=getchar();int s=,f=;
while (ch<''||ch>'') {if (ch=='-') f=-;ch=getchar();}
while (ch>=''&&ch<='') {s=(s<<)+(s<<)+ch-'';ch=getchar();}
return s*f;
}
void link(int u,int v){edge[++tot]=(EDGE){v,head[u]};head[u]=tot;}
void chkmax(int &a,int b){if (b>a) a=b;}
void chkmin(int &a,int b){if (b<a) a=b;}
void tarjan(int x,int pre){
dfn[x]=low[x]=++tim;sta[++tp]=x;
for (int i=head[x];i;i=edge[i].nxt){
int y=edge[i].to;
if (!dfn[y]){
tarjan(y,x);
chkmin(low[x],low[y]);
if (low[y]>dfn[x]) tp--;//这个必须要
if (dfn[x]==low[y]){
for (++cnt,vd[cnt].mx=vd[cnt].mi=x;sta[tp]!=x;tp--) chkmax(vd[cnt].mx,sta[tp]),chkmin(vd[cnt].mi,sta[tp]);
}
}
else if (y!=pre) chkmin(low[x],dfn[y]);
}
}
int main(){
freopen("graph.in","r",stdin);
freopen("graph.out","w",stdout);
n=read();m=read();
for (int i=,u,v;i<=m;i++){
u=read();v=read();
link(u,v);link(v,u);
}
for (int i=;i<=n;i++) if (!dfn[i]) tarjan(i,-);
for (int i=;i<=cnt;i++) lf[vd[i].mx]=vd[i].mi+;
lf[]=;rsum[]=;
for (int i=;i<=n;i++) chkmax(lf[i],lf[i-]);
for (int i=;i<=n;i++) rsum[i]=i-lf[i]++rsum[i-];
int q=read();
while (q--)
{
int x=read(),y=read();
int pos=lower_bound(lf+,lf++n,x)-lf;
ll re;
if (pos<=y)
{
re=rsum[y]-rsum[pos-];
re+=1ll*(pos-x)*(pos-x+)/;
}
else re=1ll*(y-x+)*(y-x+)/;
printf("%lld\n",re);
}
return ;
}
T2:风筝 (CF650D)
题目链接:
https://jzoj.net/senior/#contest/show/2534/1
题目:
当一阵风吹来,风筝飞上天空,为了你,而祈祷,而祝福,而感动……
oyiya 在 AK 了 IOI 之后来到了乡下,在田野中玩耍,放松身心。
他发现前面有一排小朋友在放风筝,每一个风筝有一个高度 hi,风筝的高度可能会随着小朋友的心情而改变。这时,毒瘤的 oyiya 有了一个毒瘤的 idea,他想知道改变高度之后风筝的最长严格上升子序列。oyiya 太强了表示并不想做这种水题,你能解决这个问题吗?
题解:
推荐大佬博客:https://blog.csdn.net/zearot/article/details/50857353,感谢大佬
其实我觉得这篇博客讲的很清楚了...我再讲有点冗余
其实就是分修改后两种情况,一种是b在LIS中,一种是b不在LIS中
若b在LIS中,维护一下a之前的可以转移到b的最大值,a之后的可以从b转移到的最大值。离线加树状数组的话其实很好写,就是遇到询问就在当前树状数组里查询最大值,然后再把当前元素加进树状数组。当然还可以写可持久化线段树
若b不在LIS中,判断一下少了下标a会不会影响原来的LIS,即判断下标a是否一定要出现在原来的LIS中。首先知道一个结论,对于一个序列,若一个下标多次出现在LIS中,那么这个下标在LIS的排名一定是一样的。那么就记录一个cunt数组判断有几个位置可以胜任排名i就好了
两种情况的答案取max
离线树状数组做法
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<iostream>
#include<vector>
using namespace std; const int N=1e6+;
int n,m,len,tot;
int h[N],L[N],R[N],c[N],t[N],cunt[N],a[N],b[N],ANSl[N],ANSr[N];
struct node{
int ca,id;
};
vector <node> q[N];
inline int read(){
char ch=getchar();int s=,f=;
while (ch<''||ch>'') {if (ch=='-') f=-;ch=getchar();}
while (ch>=''&&ch<='') {s=(s<<)+(s<<)+ch-'';ch=getchar();}
return s*f;
}
void init(){
sort(c+,c++tot);
len=unique(c+,c++tot)-c-;
for (int i=;i<=n;i++) h[i]=lower_bound(c+,c++len,h[i])-c;
for (int i=;i<=m;i++) b[i]=lower_bound(c+,c++len,b[i])-c;
}
void chkmax(int &a,int b) {if (b>a) a=b;}
void modify(int x,int y){
while (x<=len){
chkmax(t[x],y);
x+=x&-x;
}
}
int query(int x){
int re=;
while (x){
chkmax(re,t[x]);
x-=x&-x;
}
return re;
}
int main(){
freopen("kite.in","r",stdin);
freopen("kite.out","w",stdout);
n=read();m=read();
for (int i=;i<=n;i++) h[i]=read(),c[++tot]=h[i];
for (int i=;i<=m;i++) a[i]=read(),b[i]=read(),c[++tot]=b[i];
init();
//for (int i=1;i<=n;i++) printf("%d ",h[i]);
//printf("\n");
int k=;
for (int i=;i<=n;i++){
L[i]=max(,query(h[i]-)+);
chkmax(k,L[i]);
modify(h[i],L[i]);
}
memset(t,,sizeof(t));
for (int i=n;i;i--){
R[i]=query(len-h[i]+)+;
modify(len-h[i]+,R[i]);
}
//for (int i=1;i<=n;i++) printf("%d %d\n",L[i],R[i]);
memset(t,,sizeof(t));
for (int i=;i<=m;i++) q[a[i]].push_back((node){b[i],i});
for (int i=;i<=n;i++){
for (int j=;j<q[i].size();j++)
ANSl[q[i][j].id]=query(q[i][j].ca-);
modify(h[i],L[i]);
}
memset(t,,sizeof(t));
for (int i=n;i;i--){
for (int j=;j<q[i].size();j++)
ANSr[q[i][j].id]=query(len-q[i][j].ca);
modify(len-h[i]+,R[i]);
}
for (int i=;i<=n;i++) if (L[i]+R[i]==k+) cunt[L[i]]++;
for (int i=;i<=m;i++)
{
if (L[a[i]]+R[a[i]]!=k+)
{
printf("%d\n",max(k,ANSl[i]+ANSr[i]+));
}
else
{
if (cunt[L[a[i]]]>) printf("%d\n",max(k,ANSl[i]+ANSr[i]+));
else printf("%d\n",max(k-,ANSl[i]+ANSr[i]+));
}
}
return ;
}
在线主席树做法
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<iostream>
using namespace std; const int N=1e6+;
int n,m,len,tot,cnt;
int h[N],L[N],R[N],c[N],t[N],cunt[N],a[N],b[N],ANSl[N],ANSr[N];
int rt[N<<],lx[N<<],rx[N<<],mx[N<<];
struct node{
int ca,id;
};
inline int read(){
char ch=getchar();int s=,f=;
while (ch<''||ch>'') {if (ch=='-') f=-;ch=getchar();}
while (ch>=''&&ch<='') {s=(s<<)+(s<<)+ch-'';ch=getchar();}
return s*f;
}
void init(){
sort(c+,c++tot);
len=unique(c+,c++tot)-c-;
for (int i=;i<=n;i++) h[i]=lower_bound(c+,c++len,h[i])-c;
for (int i=;i<=m;i++) b[i]=lower_bound(c+,c++len,b[i])-c;
}
void chkmax(int &a,int b) {if (b>a) a=b;}
void modify(int x,int y){
while (x<=len){
chkmax(t[x],y);
x+=x&-x;
}
}
int query(int x){
int re=;
while (x){
chkmax(re,t[x]);
x-=x&-x;
}
return re;
}
void pushup(int o){
mx[o]=max(mx[lx[o]],mx[rx[o]]);
}
int update(int pre,int l,int r,int x,int y){
int o=++cnt;
if (l==r) {mx[o]=y;return o;}
lx[o]=lx[pre];rx[o]=rx[pre];mx[o]=mx[pre];
int mid=l+r>>;
if (x<=mid) lx[o]=update(lx[pre],l,mid,x,y);
else rx[o]=update(rx[pre],mid+,r,x,y);
pushup(o);
return o;
}
int query1(int o,int l,int r,int x){
if (!o) return ;
if (x>=r) return mx[o];
if (l>x) return ;
int mid=l+r>>;
return max(query1(lx[o],l,mid,x),query1(rx[o],mid+,r,x));
}
int query2(int o,int l,int r,int x){
if (!o) return ;
if (x<=l) return mx[o];
if (r<x) return ;
int mid=l+r>>;
return max(query2(lx[o],l,mid,x),query2(rx[o],mid+,r,x));
}
int main(){
freopen("kite.in","r",stdin);
freopen("kite.out","w",stdout);
n=read();m=read();
for (int i=;i<=n;i++) h[i]=read(),c[++tot]=h[i];
for (int i=;i<=m;i++) a[i]=read(),b[i]=read(),c[++tot]=b[i];
init();
int k=;
for (int i=;i<=n;i++){
L[i]=max(,query(h[i]-)+);
chkmax(k,L[i]);
modify(h[i],L[i]);
}
memset(t,,sizeof(t));
for (int i=n;i;i--){
R[i]=query(len-h[i]+)+;
modify(len-h[i]+,R[i]);
}
memset(rt,,sizeof(rt));cnt=;
for (int i=;i<=n;i++) rt[i]=update(rt[i-],,len,h[i],L[i]);
for (int i=;i<=m;i++) ANSl[i]=query1(rt[a[i]-],,len,b[i]-);
memset(rt,,sizeof(rt));cnt=;
for (int i=n;i;i--) rt[i]=update(rt[i+],,len,h[i],R[i]);
for (int i=;i<=m;i++) ANSr[i]=query2(rt[a[i]+],,len,b[i]+); for (int i=;i<=n;i++) if (L[i]+R[i]==k+) cunt[L[i]]++;
for (int i=;i<=m;i++)
{
if (L[a[i]]+R[a[i]]!=k+)
{
printf("%d\n",max(k,ANSl[i]+ANSr[i]+));
}
else
{
if (cunt[L[a[i]]]>) printf("%d\n",max(k,ANSl[i]+ANSr[i]+));
else printf("%d\n",max(k-,ANSl[i]+ANSr[i]+));
}
}
return ;
}
T3:种花
题目链接:
http://172.16.0.132/senior/#main/show/5921
题目:
小 H 是一个喜欢养花的女孩子。
她买了 n 株花,编号为一里香,二里香……七里香……n 里香,她想把这些花分别种在 n个不同的花盆里。
对于一种方案,第 i 个花盆里种的是 ai 里香,小 H 定义其美丽值为:
aaarticlea/png;base64,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" alt=" " />
第一行一个整数 n,第二行有 n 个整数表示 {pi},表示第i个花盆不能种pi里香。
求所有合法方案的美丽值之和
题解:
很显然这是道毒瘤的计数题,不能直接根据定义计算,我们应该计算每一部分的贡献
先不管这个,我们先定义$f_{x,y}$表示表示一共有(x+y)个元素,其中y个没有限制,另外x个被禁止放入一个位置的方案数,那么有转移:
$f_{0,0}=1$
$f_{x,0}=(x-1)\times(f_{x-1,0}+f_{x-2,0})$(错排公式)
$f_{x,y}=x \times f_{x-1,y}+y \times f_{x,y-1}$
前面两个比较显然,考虑最后一个的含义。考虑新加入一个没有限制的元素。如果该元素放置的位置是有限制的,那么这个位置以前有限制的元素就变成了没有限制的了,有x种选择方法,剩下的元素的放置方案数为$f_{x-1,y}$;如果该元素放置的位置是没有限制的,那么有y种选择方法,剩下的元素的放置方案数为$f_{x,y-1}$。
我们考虑枚举两个位置$O(1)$计算贡献,假设我们枚举的位置是i和j,分以下三种情况讨论
1. 若 $p_j$在$i$ 上, $p_i$在$j$上,那么有$f_{n−2,0}$ 种情况。贡献为 $a_1 = max(0, p_j − p_i)$。
2. 若上面两个条件只满足一个,那么有 $f_{n−3,1}$ 种情况(假设只满足$p_j$在i上,那么当$p_i$随便填一个位置,剩下的$n-2$个数就会有一个没有限制)。贡献为$a_2=\sum_{k=1}^{p_j-1}-a_1+\sum_{k=1}^{n-p_i}-a_1$。(分 别考虑$ j $在 $p_i $和 $i$ 在 $p_j$ 并减去$ i, j$ 同时在 $p_j , p_i $的情况)
3. 两个条件都不满足的有$f_{n−4,2}$种情况($p_i$和$p_j$都随便填一个位置,剩下的$n-2$个数就会有两个没有限制)。贡献为$a_3=\sum_{i=2}^{n}\sum_{j=1}^{i-1}j-a_1-a_2-(\sum_{i=1}^{p_i-1}i+\sum_{i=1}^{n-p_j}i-max(0,p_i-p_j)) $
所以答案为$\sum_{i<j} (j-i)(a_1 f_{n-2,0}+a_2 f{n-3,1}+a_3 f_{n-4,2})$
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<iostream>
using namespace std;
typedef long long ll; const int N=6e3+;
const ll mo=1e9+;
int n;
int p[N];
ll f[N][];
inline int read(){
char ch=getchar();int s=,f=;
while (ch<''||ch>'') {if (ch=='-') f=-;ch=getchar();}
while (ch>=''&&ch<='') {s=(s<<)+(s<<)+ch-'';ch=getchar();}
return s*f;
}
ll qpow(ll a,ll b){
ll re=;
for (;b;b>>=,a=a*a%mo) if (b&) re=re*a%mo;
return re;
}
ll inv(ll x) {return qpow(x,mo-);}
int main(){
freopen("derangement.in","r",stdin);
freopen("derangement.out","w",stdout);
n=read();
for (int i=;i<=n;i++) p[i]=read();
f[][]=;f[][]=;
for (int i=;i<;i++) f[][i]=f[][i-]*i%mo;
for (int i=;i<=n;i++) f[i][]=(i-)*(f[i-][]+f[i-][])%mo;
for (int i=;i<=;i++)
for (int j=;j<=n;j++) f[j][i]=(j*f[j-][i]%mo+i*f[j][i-]%mo)%mo;
ll ans=,inv12=inv(),inv2=inv(),inv4=inv();
for (int i=;i<n;i++)
for (int j=i+;j<=n;j++)
{
ll a1=max(,p[j]-p[i]);
ll a2=(p[j]*(p[j]-)%mo*inv2%mo+(n-p[i]+)*(n-p[i])%mo*inv2%mo-*a1%mo+mo)%mo;
ll a3=((n*(n+)%mo*(*n+)%mo*inv12%mo-n*(n+)%mo*inv4%mo+mo-a1-a2-p[i]*(p[i]-)%mo*inv2%mo-(n-p[j]+)*(n-p[j])%mo*inv2%mo+max(,p[i]-p[j]))%mo+mo)%mo;
ans=(ans+(j-i)*(a1*f[n-][]%mo+a2*f[n-][]%mo+a3*f[n-][]%mo)%mo)%mo;
}
printf("%lld\n",ans);
return ;
}
[JZOJ NOIP2018模拟10.21]的更多相关文章
- [jzoj NOIP2018模拟10.29]
OI生涯的最高分,来了纪中这么多天,在经历了这么多场“NOIP难度”的模拟赛之后,终于看到了真正的NOIP 今天考场上效率很高,很快码完了全部的题目,留下了足够的时间对拍和...发呆.不得不说看着电脑 ...
- [jzoj NOIP2018模拟10.23]
丢分主要是下面几个方面: 1.T2代码交错了,有个特判没写丢了10分 2.T1线段树加等差数列写错了(其实二维差分就可以,但我当时不会) 3.T3思考再三还是为了10分写上了主席树,还是写错了 总体评 ...
- [JZOJ NOIP2018模拟10.20 B组]
T1:原根(math) 题目链接: http://172.16.0.132/senior/#contest/show/2532/0 题目: 题解: 一个数m原根的个数是$\phi{(\phi{(m)} ...
- [JZOJ NOIP2018模拟10.20 A组]
由于T3数据出锅,还不清楚自己的分数...估分150,前100已经拿到了,T3的50没拍过(写的就是暴力怎么拍),感觉很不稳 考试的时候就是特别的困,大概是因为早上在房间里腐败...腐败完了才睡觉 T ...
- [JZOJ NOIP2018模拟10.19]
T1写炸了今天,期望70却落了个20...连链上的都没有写对 T3什么什么线段树分治套AC自动机,表示我完全自闭了,幸好考场上没有杠T3 总体比赛还是比较舒服,暴力分给的蛮足的,不像昨天那样 T1:林 ...
- [jzoj 5926] [NOIP2018模拟10.25] naive 的图 解题报告(kruskal重构树+二维数点)
题目链接: https://jzoj.net/senior/#main/show/5926 题目: 题解: 显然最小的最大路径在最小生成树上(最小生成树=最小瓶颈生成树) 于是我们建出kruskal重 ...
- [JZOJ 5893] [NOIP2018模拟10.4] 括号序列 解题报告 (Hash+栈+map)
题目链接: https://jzoj.net/senior/#main/show/5893 题目: 题解: 考虑暴力怎么做,我们枚举左端点,维护一个栈,依次加入元素,与栈顶元素和栈内第二个元素相同时弹 ...
- [JZOJ 5912] [NOIP2018模拟10.18] VanUSee 解题报告 (KMP+博弈)
题目链接: https://jzoj.net/senior/#contest/show/2530/2 题目: 众所周知,cqf童鞋对哲学有着深入的理解和认识,并常常将哲学思想应用在实际生活中,例如锻炼 ...
- [JZOJ 5910] [NOIP2018模拟10.18] DuLiu 解题报告 (并查集+思维)
题目链接: https://jzoj.net/senior/#contest/show/2530/0 题目: LF是毒瘤出题人中AK IOI2019,不屑于参加NOI的唯一的人.他对人说话,总是满口垃 ...
随机推荐
- h5-登录
<html> <head> <meta http-equiv="Content-Type" content="text/html; char ...
- 4.matlab基础
1 函数句柄 clear all; f1=@cos t=:pi/:pi f1(t) f2=@complex f2(,) clear all %函数句柄 f1=@char %函数句柄转换为字符串 s1= ...
- Exception异常常见属性
废话少说,直接上代码: try { int n = Convert.ToInt32("@"); } catch(Exception ex) { Console.WriteLine( ...
- 【转】sql 一对多情况下 Group by分组 结果多列合并
部分原始表数据 需求: 按routineId进行group分组 初步想法(错误): select r * from autowork.dbo.PartOnRoutine where routineId ...
- Oracle数据库基础(一)
当今主流数据库有瑞典MySQL公司的MySQL数据库,微软的SqlServer数据库,IBM公司的DB2,Oracle公司的Oracle数据库以及美国Sybase的Sybaseshujuku .数据库 ...
- 使用 Travis-CI 的五个理由
I use the service of travis-ci now for a year. In that time the continuous integration has often poi ...
- C语言中文件定位函数总结
C语言中文件定位函数主要是:fseek, ftell, fsetpos, fgetpos. 先来讲前两个函数,这是最基本的定位函数: fseek函数:能把文件指针移动到文件任何位置,其原型是:int ...
- 详解循环神经网络(Recurrent Neural Network)
本文结构: 模型 训练算法 基于 RNN 的语言模型例子 代码实现 1. 模型 和全连接网络的区别 更细致到向量级的连接图 为什么循环神经网络可以往前看任意多个输入值 循环神经网络种类繁多,今天只看最 ...
- js禁止
很多时候需要用到js禁止相关的代码: function prohibit() { // 禁止右键 $(document).ready(function() { $(document).bind(&qu ...
- 如何在ZBrush 4R7中设置背面遮罩
ZBrush 4R7中的背面遮罩是如何来设置的?当我们在进行ZBrush雕刻创作的时候,经常会不经意的雕刻到背面的物体,那么,如何防止背面的物体不被雕刻到,这就需要设置下背景遮罩了. ZBrush 4 ...