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] 题解的更多相关文章

  1. 2019.8.1 NOIP模拟测试11 反思总结

    延迟了一天来补一个反思总结 急匆匆赶回来考试,我们这边大家的状态都稍微有一点差,不过最后的成绩总体来看好像还不错XD 其实这次拿分的大都是暴力[?],除了某些专注于某道题的人以及远程爆踩我们的某学车神 ...

  2. [NOIP模拟测试38]题解

    来自达哥的问候…… A.金 显然本题的考察点在于高精而不是裴蜀定理 根据裴蜀定理易得答案为Yes当且仅当$gcd(n,m)=1$,那么考虑怎么在高精度下判互质. 如果$n,m$都能被2整除,那么显然不 ...

  3. [NOIP模拟测试31]题解

    A.math 考场乱搞拿了95,2333. 考虑裴蜀定理:$ax+by=z$存在整数解,当且仅当$gcd(a,b)|z$. 那么如果某个数能够被拼出来,就必须满足所有$a_i$的$gcd$是它的因子. ...

  4. NOIP模拟测试11「string&#183;matrix&#183;big」

    打的big出了点小问题,maxx初值我设的0然后少了10分 第二题暴力打炸 第一题剪了一些没用的枝依然40分 总分70 这是一次失败的考试 string 想到和序列那个题很像,但我没做序列,考场回忆学 ...

  5. NOIP模拟测试11

    这次考试T1想到了正解没有去实现,然后就死了,不过我估计就算想到正解也会挂(26^2和暴力一个分),肝了两个小时T2屁都没蹦出来,T3没有搞清那个式子的含义. (不过一分没挂) T1:string 开 ...

  6. [NOIP模拟测试30]题解

    A.Return 出题人大概是怕自己的中文十级没人知道,所以写了这么一个***题面.可能又觉得这题太水怕全场A掉后自己面子过不去,于是又故意把输出格式说的含糊不清.(鬼知道"那么输出-1&q ...

  7. [NOIP模拟测试12]题解

    A. 找规律题.儿子的编号减去 小于它编号的最大的fibonacci数 即可得到它父亲的编号. 然后两个节点都暴力上跳就好了.预处理一下fibonacci数,每次二分查找即可. #include< ...

  8. 「题解」NOIP模拟测试题解乱写II(36)

    毕竟考得太频繁了于是不可能每次考试都写题解.(我解释个什么劲啊又没有人看) 甚至有的题目都没有改掉.跑过来写题解一方面是总结,另一方面也是放松了. NOIP模拟测试36 T1字符 这题我完全懵逼了.就 ...

  9. 2019.8.3 [HZOI]NOIP模拟测试12 C. 分组

    2019.8.3 [HZOI]NOIP模拟测试12 C. 分组 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 刚看这题觉得很难,于是数据点分治 k只有1和2两种,分别 ...

随机推荐

  1. 【PowerOJ1740&网络流24题】圆桌聚餐(最大流)

    题意: 来自n个不同国家的代表开会,每个国家代表数为ci 会场有m张圆桌,每张桌子可容纳mi人 不希望有同一个国家的代表在同一张桌子上就餐 设计一个合法方案 (n,m<=300) 思路:最大流, ...

  2. jQuery函数API,各版本新特性汇总

    jQuery API 速查表 选择器 基本 #id element .class * selector1,selector2,selectorN 层级 ancestor descendant pare ...

  3. JS-模拟printf

    function printf(){ var args = [].slice.call(arguments), fmt = args.shift(), args_index = 0; ///%(填充的 ...

  4. Mamen所需要的jar包怎么生成

    Mamen所需要的jar包怎么生成 使用 mamen 难免碰到,不知道的 jar 包,不知道怎么在 pom 文件中写,分享一个网址,可以把你想要的 jar 包生成 pom 配置文件,个人感觉非常好用. ...

  5. vue消息提示Message

    https://www.iviewui.com/components/message this.$Message.info(config) this.$Message.success(config) ...

  6. Single Page Application

    single page web application,SPA,就是只有一张Web页面的应用,是加载单个HTML 页面并在用户与应用程序交互时动态更新该页面的Web应用程序.   单页Web应用(si ...

  7. ubuntu16安装,配置前端开发环境

    1.安装ubuntu    使用usio制作U盘安装工具 2.安装搜狗输入法 3.安装QQ 4.安装nodejs node-v0.12.4 node-v0.12.4.tar.gz root@ubunt ...

  8. java 多级图的最短路径

    求最短路径众所周知有Dijistra算法.Bellman-ford等,除了这些算法,用动态规划也可以求出最短路径,时间复杂度为O(n^2), 跟没有优化的Dijistra算法一样(优化后的Dijist ...

  9. UVA_548Tree

    这是一个很经典的建树,然而当时不会!!!! 给你一个中序和后序 先建一个二叉树,然后找最优解(最优解就是一个叶子节点到根节点权值最小, 同时本身权值最小) //生成一棵树 int build(int ...

  10. Cocos2d之运行Test项目

    |   版权声明:本文为博主原创文章,未经博主允许不得转载. 1. 打开Test项目 路径为   C:\Dev\cocos2d-x-3.8.1\build 2.设定cpp-tests为启动项(当cpp ...