[NOIP模拟测试11] 题解
A.string
和河北的一道省选题很像。考场上写的暴力桶排,正解其实就是优化一下这个思路。
开线段树维护字符串中每个字母出现的次数。对于每条询问,区间查询、区间赋值维护即可。
另外,本题卡常严重,正解能被卡到40到90不等。所以直接循环展开乱搞一波?
暴力40分代码:
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int N=;
int a[N],bu[],n,m;
char str[N];
int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<='')x=x*+ch-'',ch=getchar();
return x*f;
}
void busort(int op,int l,int r)
{
for(int i=l;i<=r;i++)
bu[a[i]]++;
int tot=;
if(op)
{
for(int i=;i<=;i++)
while(bu[i])a[l+(tot++)]=i,bu[i]--;
}
else
{
for(int i=;i>=;i--)
while(bu[i])a[l+(tot++)]=i,bu[i]--;
}
}
int main()
{
n=read();m=read();
scanf("%s",str+);
for(int i=;i<=n;i++)
a[i]=(int)str[i];
while(m--)
{
int l=read(),r=read(),op=read();
busort(op,l,r);
}
for(int i=;i<=n;i++)
{
char ch=(char)a[i];
printf("%c",ch);
}
return ;
}
被卡的90分代码:
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int N=;
int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<='')x=x*+ch-'',ch=getchar();
return x*f;
}
int n,m,len;
char str[N],ans[N];
#define ls(k) k<<1
#define rs(k) k<<1|1
int num[N<<][],lz[N<<],le[N<<],re[N<<];
int res[];
void up(int k)
{
for(int i=;i<=;i++)
num[k][i]=num[ls(k)][i]+num[rs(k)][i];
}
void build(int k,int l,int r)
{
lz[k]=;le[k]=l,re[k]=r;
if(l==r)
{
num[k][str[l]-'a'+]=;
return ;
}
int mid=l+r>>;
build(ls(k),l,mid);
build(rs(k),mid+,r);
up(k);
}
void down(int k)
{
memset(num[ls(k)],,sizeof(num[ls(k)]));
memset(num[rs(k)],,sizeof(num[rs(k)]));
num[ls(k)][lz[k]]=re[ls(k)]-le[ls(k)]+;
num[rs(k)][lz[k]]=re[rs(k)]-le[rs(k)]+;
lz[ls(k)]=lz[rs(k)]=lz[k];
lz[k]=;
}
void query(int k,int L,int R)
{
if(le[k]>=L&&R>=re[k])
{
for(int i=;i<=;i++)
res[i]+=num[k][i];
return ;
}
int mid=le[k]+re[k]>>;
if(lz[k])down(k);
if(L<=mid)query(ls(k),L,R);
if(R>mid)query(rs(k),L,R);
}
void change(int k,int L,int R,int val)
{
if(le[k]>=L&&R>=re[k])
{
memset(num[k],,sizeof(num[k]));
num[k][val]=re[k]-le[k]+;
lz[k]=val;
return ;
}
int mid=le[k]+re[k]>>;
if(lz[k])down(k);
if(L<=mid)change(ls(k),L,R,val);
if(R>mid)change(rs(k),L,R,val);
up(k);
}
void cacl(int k)
{
if(le[k]==re[k])
{
for(int i=;i<=;i++)
if(num[k][i])
{
ans[++len]=i-+'a';
return ;
}
}
if(lz[k])down(k);
cacl(ls(k));
cacl(rs(k));
}
int main()
{
n=read();m=read();
scanf("%s",str+);
build(,,n);
for(int i=;i<=m;i++)
{
int l=read(),r=read(),op=read();
memset(res,,sizeof(res));
query(,l,r);
if(op)
{
for(int j=;j<=;j++)
if(res[j])
change(,l,l+res[j]-,j),l+=res[j];
}
else
{
for(int j=;j>=;j--)
if(res[j])
change(,l,l+res[j]-,j),l+=res[j];
}
}
cacl();
printf("%s\n",ans+);
return ;
}
丧心病狂科学打表的循环展开代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#define rint register int
using namespace std;
const int N=;
int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<='')x=x*+ch-'',ch=getchar();
return x*f;
}
int n,m,len;
char str[N],ans[N];
#define ls(k) k<<1
#define rs(k) k<<1|1
int num[N<<][],lz[N<<],le[N<<],re[N<<];
int res[];
void up(int k)
{
num[k][]=num[ls(k)][]+num[rs(k)][];
num[k][]=num[ls(k)][]+num[rs(k)][];
num[k][]=num[ls(k)][]+num[rs(k)][];
num[k][]=num[ls(k)][]+num[rs(k)][];
num[k][]=num[ls(k)][]+num[rs(k)][];
num[k][]=num[ls(k)][]+num[rs(k)][];
num[k][]=num[ls(k)][]+num[rs(k)][];
num[k][]=num[ls(k)][]+num[rs(k)][];
num[k][]=num[ls(k)][]+num[rs(k)][];
num[k][]=num[ls(k)][]+num[rs(k)][];
num[k][]=num[ls(k)][]+num[rs(k)][];
num[k][]=num[ls(k)][]+num[rs(k)][];
num[k][]=num[ls(k)][]+num[rs(k)][];
num[k][]=num[ls(k)][]+num[rs(k)][];
num[k][]=num[ls(k)][]+num[rs(k)][];
num[k][]=num[ls(k)][]+num[rs(k)][];
num[k][]=num[ls(k)][]+num[rs(k)][];
num[k][]=num[ls(k)][]+num[rs(k)][];
num[k][]=num[ls(k)][]+num[rs(k)][];
num[k][]=num[ls(k)][]+num[rs(k)][];
num[k][]=num[ls(k)][]+num[rs(k)][];
num[k][]=num[ls(k)][]+num[rs(k)][];
num[k][]=num[ls(k)][]+num[rs(k)][];
num[k][]=num[ls(k)][]+num[rs(k)][];
num[k][]=num[ls(k)][]+num[rs(k)][];
num[k][]=num[ls(k)][]+num[rs(k)][];
}
void build(int k,int l,int r)
{
lz[k]=;le[k]=l,re[k]=r;
if(l==r)
{
num[k][str[l]-'a'+]=;
return ;
}
int mid=l+r>>;
build(ls(k),l,mid);
build(rs(k),mid+,r);
up(k);
}
void down(int k)
{
memset(num[ls(k)],,sizeof(num[ls(k)]));
memset(num[rs(k)],,sizeof(num[rs(k)]));
num[ls(k)][lz[k]]=re[ls(k)]-le[ls(k)]+;
num[rs(k)][lz[k]]=re[rs(k)]-le[rs(k)]+;
lz[ls(k)]=lz[rs(k)]=lz[k];
lz[k]=;
}
void query(int k,int L,int R)
{
if(le[k]>=L&&R>=re[k])
{
res[]+=num[k][];
res[]+=num[k][];
res[]+=num[k][];
res[]+=num[k][];
res[]+=num[k][];
res[]+=num[k][];
res[]+=num[k][];
res[]+=num[k][];
res[]+=num[k][];
res[]+=num[k][];
res[]+=num[k][];
res[]+=num[k][];
res[]+=num[k][];
res[]+=num[k][];
res[]+=num[k][];
res[]+=num[k][];
res[]+=num[k][];
res[]+=num[k][];
res[]+=num[k][];
res[]+=num[k][];
res[]+=num[k][];
res[]+=num[k][];
res[]+=num[k][];
res[]+=num[k][];
res[]+=num[k][];
res[]+=num[k][];
return ;
}
int mid=le[k]+re[k]>>;
if(lz[k])down(k);
if(L<=mid)query(ls(k),L,R);
if(R>mid)query(rs(k),L,R);
}
void change(int k,int L,int R,int val)
{
if(le[k]>=L&&R>=re[k])
{
memset(num[k],,sizeof(num[k]));
num[k][val]=re[k]-le[k]+;
lz[k]=val;
return ;
}
int mid=le[k]+re[k]>>;
if(lz[k])down(k);
if(L<=mid)change(ls(k),L,R,val);
if(R>mid)change(rs(k),L,R,val);
up(k);
}
void cacl(int k)
{
if(le[k]==re[k])
{
if(num[k][]){ans[++len]=-+'a';return ;}
if(num[k][]){ans[++len]=-+'a';return ;}
if(num[k][]){ans[++len]=-+'a';return ;}
if(num[k][]){ans[++len]=-+'a';return ;}
if(num[k][]){ans[++len]=-+'a';return ;}
if(num[k][]){ans[++len]=-+'a';return ;}
if(num[k][]){ans[++len]=-+'a';return ;}
if(num[k][]){ans[++len]=-+'a';return ;}
if(num[k][]){ans[++len]=-+'a';return ;}
if(num[k][]){ans[++len]=-+'a';return ;}
if(num[k][]){ans[++len]=-+'a';return ;}
if(num[k][]){ans[++len]=-+'a';return ;}
if(num[k][]){ans[++len]=-+'a';return ;}
if(num[k][]){ans[++len]=-+'a';return ;}
if(num[k][]){ans[++len]=-+'a';return ;}
if(num[k][]){ans[++len]=-+'a';return ;}
if(num[k][]){ans[++len]=-+'a';return ;}
if(num[k][]){ans[++len]=-+'a';return ;}
if(num[k][]){ans[++len]=-+'a';return ;}
if(num[k][]){ans[++len]=-+'a';return ;}
if(num[k][]){ans[++len]=-+'a';return ;}
if(num[k][]){ans[++len]=-+'a';return ;}
if(num[k][]){ans[++len]=-+'a';return ;}
if(num[k][]){ans[++len]=-+'a';return ;}
if(num[k][]){ans[++len]=-+'a';return ;}
if(num[k][]){ans[++len]=-+'a';return ;}
}
if(lz[k])down(k);
cacl(ls(k));
cacl(rs(k));
}
int main()
{
n=read();m=read();
scanf("%s",str+);
build(,,n);
for(rint i=;i<=m;i++)
{
int l=read(),r=read(),op=read();
memset(res,,sizeof(res));
query(,l,r);
if(op)
{
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
}
else
{
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
if(res[])change(,l,l+res[]-,),l+=res[];
}
}
cacl();
printf("%s\n",ans+);
return ;
}
B.matrix
神dp。状态数组我估计一辈子都想不出来。
(虽然题意不明 似乎默认限制区间外必填0?)
我们把构造矩阵的过程看作往矩阵里填1的过程,设$f[i][j]$为填到第i列,有j个1在右侧限制区间里的方案数。
设$lnum[i]$为到i列时已结束的左限制区间的个数,$rnum[i]$为到i列时已开始的右限制区间的个数。
转移时左右区间分别考虑:
对于右区间,考虑到i列放与不放即可。如果不放的话就直接继承状态,即$f[i][j]+=f[i-1][j]$.如果放,则有$f[i][j+1]+=f[i-1][j]*(rnum[i]-j)$,解释一下:放1肯定得在已开始的右区间里放,但是还要除去已经放了的j个右区间。
对于左区间,我们只在恰好经过它的结束点时对它进行考虑。既然有j个1放在右限制区间,已经转移了i列,那么一定有i-j个1放在左限制区间,毕竟每列只放一个。又因为有$lnum[i-1]$个左区间已经结束并处理过了,所以留给恰在第i列结束的左区间的1只有$i-j-lnum[i-1]$个(当然,这些1也可以放在之前的某一列里),那么对方案的贡献就要乘上$A_{i-j-lnum[i-1]}^{lnum[i]-lnum[i-1]}$了。
排列数打表或逆元求皆可。
//dp[i][j]:到第i列,j个1在各行的右区间
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=;
const ll mod=;
int L[N],R[N],numl[N],numr[N],n,m;
ll dp[N][N],A[N][N];
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
{
scanf("%d%d",&L[i],&R[i]);
numl[L[i]]++;numr[R[i]]++;
}
for(int i=;i<=m;i++)
numl[i]+=numl[i-],numr[i]+=numr[i-];
for(int i=;i<=m;i++)
{
A[i][]=;
for(int j=;j<=i;j++)
A[i][j]=A[i][j-]*1LL*(i-j+)%mod;
}
dp[][]=;A[][]=;
for(int i=;i<=m;i++)
{
for(int j=;j<=n;j++)
{
if(i-j-numl[i-]<numl[i]-numl[i-])//左:在这一列结束的左区间能放几个1
{
dp[i][j]=;
continue;
}
(dp[i][j]*=A[i-j-numl[i-]][numl[i]-numl[i-]])%=mod;
(dp[i+][j]+=dp[i][j])%=mod;
(dp[i+][j+]+=dp[i][j]*1LL*(numr[i+]-j))%=mod;
// cout<<dp[i][j]<<endl;
}
}
cout<<dp[m][n]<<endl;
return ;
}
C.
sb对手干的破事其实就是循环左移(最靠前的一位挪到后面,剩下全体左移一位)
异或满足交换律结合律,那么就可以先利用前后缀求出每次除了初值外的异或和,将它们插入一棵01Trie,并通过对它进行dfs得出结果。
如果儿子只有一个,我们选x时就能取与它相反的一位从而让这位成为1,所以在计答案时这一位为1;如果儿子有两个,不论我们这位选0还是1,对手都会取相同的一位使这一位成为0,所以答案中这一位只能为0。
复杂度$O(nm)$
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int N=;
int a[N],trie[N*][],xors[N],sxor[N];
int tot,ans,ansnum,n,m;
void ins(int num)
{
int root=;
for(int i=n-;i>=;i--)
{
int x=(num>>i)&;
if(!trie[root][x])trie[root][x]=++tot;
root=trie[root][x];
}
}
void dfs(int x,int val,int pos)
{
if(pos==)
{
if(val>ans)ans=val,ansnum=;
else if(val==ans)ansnum++;
return ;
}
if(!trie[x][]||!trie[x][])dfs(trie[x][]+trie[x][],val|(pos>>),pos>>);
else dfs(trie[x][],val,pos>>),dfs(trie[x][],val,pos>>);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)scanf("%d",&a[i]);
sxor[]=a[];
for(int i=;i<=m;i++)
sxor[i]=sxor[i-]^a[i];
xors[m]=a[m];
for(int i=m-;i>=;i--)
xors[i]=xors[i+]^a[i];
for(int i=;i<=m;i++)
ins(xors[i+]^(((sxor[i]<<)/(<<n)+(sxor[i]<<))%(<<n)));
dfs(,,<<n);
cout<<ans<<endl<<ansnum<<endl;
return ;
}
UPD:之前说T3那个式子叫逻辑左移?不对不对,被亚历克斯鹅科普了一下,应该是循环左移(意会为主好吧)。
[NOIP模拟测试11] 题解的更多相关文章
- 2019.8.1 NOIP模拟测试11 反思总结
延迟了一天来补一个反思总结 急匆匆赶回来考试,我们这边大家的状态都稍微有一点差,不过最后的成绩总体来看好像还不错XD 其实这次拿分的大都是暴力[?],除了某些专注于某道题的人以及远程爆踩我们的某学车神 ...
- [NOIP模拟测试38]题解
来自达哥的问候…… A.金 显然本题的考察点在于高精而不是裴蜀定理 根据裴蜀定理易得答案为Yes当且仅当$gcd(n,m)=1$,那么考虑怎么在高精度下判互质. 如果$n,m$都能被2整除,那么显然不 ...
- [NOIP模拟测试31]题解
A.math 考场乱搞拿了95,2333. 考虑裴蜀定理:$ax+by=z$存在整数解,当且仅当$gcd(a,b)|z$. 那么如果某个数能够被拼出来,就必须满足所有$a_i$的$gcd$是它的因子. ...
- NOIP模拟测试11「string·matrix·big」
打的big出了点小问题,maxx初值我设的0然后少了10分 第二题暴力打炸 第一题剪了一些没用的枝依然40分 总分70 这是一次失败的考试 string 想到和序列那个题很像,但我没做序列,考场回忆学 ...
- NOIP模拟测试11
这次考试T1想到了正解没有去实现,然后就死了,不过我估计就算想到正解也会挂(26^2和暴力一个分),肝了两个小时T2屁都没蹦出来,T3没有搞清那个式子的含义. (不过一分没挂) T1:string 开 ...
- [NOIP模拟测试30]题解
A.Return 出题人大概是怕自己的中文十级没人知道,所以写了这么一个***题面.可能又觉得这题太水怕全场A掉后自己面子过不去,于是又故意把输出格式说的含糊不清.(鬼知道"那么输出-1&q ...
- [NOIP模拟测试12]题解
A. 找规律题.儿子的编号减去 小于它编号的最大的fibonacci数 即可得到它父亲的编号. 然后两个节点都暴力上跳就好了.预处理一下fibonacci数,每次二分查找即可. #include< ...
- 「题解」NOIP模拟测试题解乱写II(36)
毕竟考得太频繁了于是不可能每次考试都写题解.(我解释个什么劲啊又没有人看) 甚至有的题目都没有改掉.跑过来写题解一方面是总结,另一方面也是放松了. NOIP模拟测试36 T1字符 这题我完全懵逼了.就 ...
- 2019.8.3 [HZOI]NOIP模拟测试12 C. 分组
2019.8.3 [HZOI]NOIP模拟测试12 C. 分组 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 刚看这题觉得很难,于是数据点分治 k只有1和2两种,分别 ...
随机推荐
- 10个优秀的 Web UI库/框架
UI(User Interface)即用户界面,也称人机界面.是指用户和某些系统进行交互方法的集合,实现信息的内部形式与人类可以接受形式之间的转换.本文为WUI用户整理了10个优秀的 Web UI 库 ...
- websocket 文件上传
<template> <div class="pad20"> <input id="file" ref="f ...
- cent OS 7 下安装 python 3.6
step1:安装依赖环境 # yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readli ...
- jquery+javascript触发a标签的点击事件
今天项目经理跟我说window.open()在一些浏览器上会被拦截,当时的解决方案是:用a标签的target="_blank"属性也可以打开窗体页面 于是解决了A问题出现了B问题: ...
- IIS日志如何记录X-Forwarded-For
起因 最近因为某个站点的流量异常,需要统计一下服务器的来源IP,本来开一下IIS日志就能搞定的事儿,但不幸的是生产服务器使用F5做了负载均衡,IIS日志无法记录到真实IP,真实的IP在"x- ...
- img点击放大的js实现
业务需要,从后台获取图片列表,用img标签展示,由于图片太小看不清,需要点击放大,类似如下效果: 点击后放大(由于图片高度超出了页面,需要通过overflow:auto;设置滚动条,点击放大图片回到列 ...
- zabbix-Graphs
图形 概述 随着大量的监控数据被采集到Zabbix中,如果用户可以以可视化的表现形式来查看发生了什么事情,那么和仅仅只有数字的表现形式比起来则更加轻松. 以下是进行图形设置的地方.图形可以一目了然地掌 ...
- 粗糙的区别prepareStatement:(为Statement的子类)与Statement
区别: prepareStatement:(为Statement的子类) conn = DBFactory.getInstance().getImpl().getConnection(); //方式一 ...
- Permission denied
记录在一次启动tomcat时提示:Permission denied 信息. 解释一下Permission denied的意思-没有权限 解决办法: sudo chmod -R 777 某一目录其中- ...
- 在MyEclipse中更换或修改svn的用户名和密码
1.通过删除SVN客户端的账号配置文件 (1)找到我们使用的客户端配置文件,Windows XP中的位置是在系统盘的Documents and Settings\Administrator\A ...