T1 回文

解题思路

原来 \(n^3\) 可以过 500 。。。

先枚举一下路径长度,对于同一路径长度点数最多是 \(n\) 个,我们可以接着枚举从 \((n,m)\) 出发的路径长度相同的点。

然后对于字母相同的位置向下一层转移。

DP 数组可以只开三维 \(f_{i,j,k}\) 表示从 \((1,1)\) 出发到达 \((i,j)\) 点,从 \((n,m)\) 出发的点目前横坐标与出发点差值是 \(k\) 。

由于路径相同因此我们也可以确定对应的纵坐标,代码实现不难,但是有一点卡常。

code

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=510,M=90,mod=993244853;
int n,m,len,ans,f[N][N][N];
int d1[10]={0,-1,0,-1,0};
int d2[10]={0,0,-1,0,-1};
int d3[10]={0,1,1,0,0};
int d4[10]={0,0,0,1,1};
vector< pair<int,int> > p[N<<1][30],q[N<<1][30];
char s[N][N];
#define add(x,y) {x+=y;if(x>=mod)x-=mod;}
int main()
{
freopen("palin.in","r",stdin); freopen("palin.out","w",stdout);
n=read(); m=read(); len=(n+m-1)>>1;
for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(i+j-1<=len) p[i+j-1][s[i][j]-'a'].push_back(make_pair(i,j));
else q[(n-i+1)+(m-j+1)-1][s[i][j]-'a'].push_back(make_pair(i,j));
if(s[1][1]!=s[n][m]) printf("0"),exit(0);
f[1][1][n]=1;
for(int l=1;l<=len;l++)
for(int col=0;col<26;col++)
for(auto it1:p[l][col])
for(auto it2:q[l][col])
for(int k=1;k<=4;k++)
{
int i=it1.first,j=it1.second,x=it2.first,y=it2.second;
int ni=i+d3[k],nj=j+d4[k],nx=x+d1[k],ny=y+d2[k];
if(s[ni][nj]==s[nx][ny]) add(f[ni][nj][nx],f[i][j][x]);
}
if((n+m-1)&1)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if((i+j-1)==len+1)
for(int k=1;k<=4;k++)
add(ans,f[i+d1[k]][j+d2[k]][i+d3[k]]);
}
else
{
for(int col=0;col<26;col++)
for(auto it:p[len][col])
{
int i=it.first,j=it.second;
for(int k=2;k<=3;k++)
{
int x=i+d3[k],y=j+d4[k];
add(ans,f[i][j][x]);
}
}
}
printf("%d",ans);
return 0;
}

T2 快速排序

解题思路

发现其实题目给的是对于操作区间的第一个数字为基准进行的快速排序。

那么如果第一个数字是 \(nan\) 的话,显然这次操作不会改变序列中任何一个数字的位置。

那么如果第一个数字不是 \(nan\) 的话,就是把它后面所有小于它的数字都放到它前面,其余的东西照常做就好了。

可以用 multiset 维护或者排序一遍直接指针扫。

code

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"RP++"<<endl
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=5e5+10;
int T,n,cnt,ans[N];
struct Node{bool jud;int val;}s[N];
multiset< pair<int,int> > res;
bool vis[N];
bool operator < (const Node& x, const Node& y)
{
if(x.jud || y.jud)
return false;
return x.val < y.val;
}
void solve()
{
n=read(); cnt=0; string ch;
for(int i=1;i<=n;i++)
{
cin>>ch; vis[i]=false; if(ch[0]=='n'){s[i].jud=true;continue;}
int x=0; for(int j=0;j<ch.size();j++) x=(x<<1)+(x<<3)+(ch[j]^48);
s[i].jud=false; s[i].val=x; res.insert(make_pair(s[i].val,i));
}
for(int i=1;i<=n;i++)
{
if(vis[i]) continue;
if(s[i].jud){ans[++cnt]=-1;continue;}
while((*res.begin()).first<s[i].val)
{
ans[++cnt]=(*res.begin()).first;
vis[(*res.begin()).second]=true; res.erase(res.begin());
}
ans[++cnt]=(*res.begin()).first;
vis[(*res.begin()).second]=true; res.erase(res.begin());
}
for(int i=1;i<=n;i++) if(ans[i]==-1) printf("nan ");else printf("%lld ",ans[i]);
putchar('\n');
}
#undef int
int main()
{
#define int long long
freopen("qsort.in","r",stdin); freopen("qsort.out","w",stdout);
T=read(); while(T--) solve();
return 0;
}

T3 混乱邪恶

解题思路

好像是一道高联题,然而我并不是特别会证明。

肯定是要先排序的,那么先让 \(2i\) 和 \(2i-1\) 分到不同的组,两个的差值记为 \(d_i\) 。

然后对于所有的 \(d\) 进行排序选择最大的与最小的相减,将差值计入集合,相当于是把较小值所代表的集合的符号进行了更改。

最后 DFS 一遍输出答案就好了。

code

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"RP++"<<endl
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=2e6+10;
int n,m,cnt,id,all,d[N],ans[N];
struct Node{int id,dat;}s[N];
vector< pair<int,int> > v[N];
multiset< pair<int,int> > res;
bool comp(Node x,Node y){if(x.dat!=y.dat)return x.dat<y.dat;return x.id<y.id;}
void dfs(int x,int flag)
{
if(!v[x].size()) return ans[s[x].id]=flag,void();
for(auto it:v[x])
dfs(it.first,flag*it.second);
}
#undef int
int main()
{
#define int long long
freopen("chaoticevil.in","r",stdin); freopen("chaoticevil.out","w",stdout);
cnt=n=read(); m=read(); printf("NP-Hard solved\n");
for(int i=1;i<=n;i++) s[i].dat=read(),s[i].id=i; if(n&1) n++;
sort(s+1,s+n+1,comp); id=n;
for(int i=1;i<=n/2;i++)
all+=(s[2*i].dat-s[2*i-1].dat!=1),id++,v[id].push_back(make_pair(2*i-1,-1)),
v[id].push_back(make_pair(2*i,1)),res.insert(make_pair(s[2*i].dat-s[2*i-1].dat,id));
while(all)
{
auto t1=*res.begin(),t2=*res.rbegin();
all-=(t1.first!=1)+(t2.first!=1); all+=(t2.first-t1.first!=1);
pair<int,int> temp=make_pair(t2.first-t1.first,++id);
v[id].push_back(make_pair(t1.second,-1)); v[id].push_back(make_pair(t2.second,1));
res.erase(res.find(t1)); res.erase(res.find(t2)); res.insert(temp);
}
int flag=1; for(auto it:res) dfs(it.second,flag),flag=-flag;
for(int i=1;i<=cnt;i++) printf("%lld ",ans[i]);
return 0;
}

T4 校门外歪脖树上的鸽子

解题思路

把 \([l,r]\) 区间上的修改视为 \(l-1\) 以及 \(r+1\) 这两个点所连接的整个路径。

开两颗线段树维护,对于左边的这条链每一次给对应父亲节点的右子树加入贡献,右边的这条链则相反。

对于询问操作也是类似的进行查询。

code

#include<bits/stdc++.h>
#define int long long
#define ls x<<1
#define rs x<<1|1
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=4e5+10;
int n,m,root,tim,dfn[N],siz[N],son[N],topp[N],fa[N],dep[N],id[N],ch[N][2],vis[N];
struct Segment_tree
{
int bas[N];
struct Node{int l,r,dat,laz,siz;}tre[N<<2];
inline void add(int x,int val){tre[x].dat+=val*tre[x].siz;tre[x].laz+=val;}
#define push_up(x) tre[x].dat=tre[ls].dat+tre[rs].dat
#define push_down(x) add(ls,tre[x].laz),add(rs,tre[x].laz),tre[x].laz=0
void build(int x,int l,int r)
{
if(l==r) return tre[x].siz=bas[l],void();
int mid=(l+r)>>1; build(ls,l,mid); build(rs,mid+1,r);
push_up(x); tre[x].siz=tre[ls].siz+tre[rs].siz;
}
void insert(int x,int l,int r,int L,int R,int val)
{
if(L>R) return ;
if(L<=l&&r<=R) return add(x,val),void();
int mid=(l+r)>>1; if(tre[x].laz) push_down(x);
if(L<=mid) insert(ls,l,mid,L,R,val);
if(R>mid) insert(rs,mid+1,r,L,R,val);
push_up(x);
}
int query(int x,int l,int r,int L,int R)
{
if(L<=l&&r<=R) return tre[x].dat;
int mid=(l+r)>>1,sum=0; if(tre[x].laz) push_down(x);
if(L<=mid) sum+=query(ls,l,mid,L,R);
if(R>mid) sum+=query(rs,mid+1,r,L,R);
return sum;
}
}L,R;
void dfs1(int x)
{
if(!ch[x][0]&&!ch[x][1]) siz[x]=1;
for(int i=0;i<=1;i++)
{
int to=ch[x][i]; if(!to) continue;
fa[to]=x; dep[to]=dep[x]+1; dfs1(to);
siz[x]+=siz[to]; if(siz[son[x]]<siz[to]) son[x]=to;
}
}
void dfs2(int x,int tp)
{
topp[x]=tp; dfn[x]=++tim;
if(son[x]) dfs2(son[x],tp);
for(int i=0;i<=1;i++)
if(ch[x][i]&&!dfn[ch[x][i]])
dfs2(ch[x][i],ch[x][i]);
R.bas[dfn[ch[x][1]]]=siz[ch[x][0]];
L.bas[dfn[ch[x][0]]]=siz[ch[x][1]];
}
void update(int x,int y,int val)
{
x=id[x-1]; y=id[y+1]; int lasx=x,lasy=y;
while(topp[x]^topp[y])
if(dep[topp[x]]<dep[topp[y]])
R.insert(1,1,tim,dfn[topp[y]],dfn[y],val),lasy=topp[y],y=fa[topp[y]];
else L.insert(1,1,tim,dfn[topp[x]],dfn[x],val),lasx=topp[x],x=fa[topp[x]];
if(dep[x]<dep[y]) R.insert(1,1,tim,dfn[x]+2,dfn[y],val),L.insert(1,1,tim,dfn[lasx],dfn[lasx],-val);
else L.insert(1,1,tim,dfn[y]+2,dfn[x],val),R.insert(1,1,tim,dfn[lasy],dfn[lasy],-val);
}
int query(int x,int y)
{
x=id[x-1]; y=id[y+1]; int lasx=x,lasy=y,sum=0;
while(topp[x]^topp[y])
if(dep[topp[x]]<dep[topp[y]])
sum+=R.query(1,1,tim,dfn[topp[y]],dfn[y]),lasy=topp[y],y=fa[topp[y]];
else sum+=L.query(1,1,tim,dfn[topp[x]],dfn[x]),lasx=topp[x],x=fa[topp[x]];
if(dep[x]<dep[y]) sum+=R.query(1,1,tim,dfn[x]+2,dfn[y])-L.query(1,1,tim,dfn[lasx],dfn[lasx]);
else sum+=L.query(1,1,tim,dfn[y]+2,dfn[x])-R.query(1,1,tim,dfn[lasy],dfn[lasy]);
return sum;
}
#undef int
int main()
{
#define int long long
freopen("pigeons.in","r",stdin); freopen("pigeons.out","w",stdout);
int opt,x,y,z; n=read(); m=read();
for(int i=1;i<n;i++) vis[ch[i+n][0]=read()]=true,vis[ch[i+n][1]=read()]=true;
for(int i=1;i<=2*n;i++) if(!vis[i]){root=i;break;}
ch[2*n+1][0]=2*n; ch[2*n+1][1]=root; ch[2*n+3][0]=2*n+1; ch[2*n+3][1]=2*n+2;
for(int i=1;i<=n;i++) id[i]=i; id[0]=2*n; id[n+1]=2*n+2; root=2*n+3;
dfs1(root); dfs2(root,root); L.build(1,1,tim); R.build(1,1,tim);
while(m--){opt=read(); x=read(); y=read();if(opt==1) z=read(),update(x,y,z);else printf("%lld\n",query(x,y));}
return 0;
}

NOIP模拟90(多校23)的更多相关文章

  1. NOIP模拟83(多校16)

    前言 CSP之后第一次模拟赛,感觉考的一般. 不得不吐槽多校联测 OJ 上的评测机是真的慢... T1 树上的数 解题思路 感觉自己思维有些固化了,一看题目就感觉是线段树. 考完之后才想起来这玩意直接 ...

  2. Noip模拟46 2021.8.23

    给了签到题,但除了签到题其他的什么也不会.... T1 数数 人均$AC$,没什么好说的,就是排个序,然后双指针交换着往中间移 1 #include<bits/stdc++.h> 2 #d ...

  3. NOIP模拟84(多校17)

    T1 宝藏 解题思路 考场上一眼出 \(nlog^2\) 做法,然后没看见是 1s 3e5 的数据,我竟然以为自己切了?? 考完之后尝试着把二分改为指针的移动,然后就过了??或许是数据水吧,感觉自己的 ...

  4. NOIP模拟92(多校25)

    前言 所以说这次是 HZOI 多校联测巅峰????(题目,数据过水??) T1 石子合并 解题思路 签到题. 发现我们可以给每个数字附一个正负号,每个数字的贡献就是它本身乘上这个符号. 发现至少应该有 ...

  5. NOIP模拟85(多校18)

    前言 好像每个题目背景所描述的人都是某部番里的角色,热切好像都挺惨的(情感上的惨). 然后我只知道 T1 的莓,确实挺惨... T1 莓良心 解题思路 首先答案只与 \(w\) 的和有关系,于是问题就 ...

  6. NOIP模拟86(多校19)

    T1 特殊字符串 解题思路 \(f_{i,j}\) 表示前 \(i\) 个字符中结尾为 \(j\) 的最大贡献. 转移枚举当前位置于之前位置结尾的组合加上贡献即可. 对于边界问题,容易发现选择 1 一 ...

  7. NOIP模拟88(多校21)

    前言 对于这套题的总体感觉就是难,然后就是自己很菜... 对于 T1 考试时只会一个最垃圾的背包,考完之后对于思路这一块也不是很顺利,大概这就是薄弱的地方吧. 然后 T2 是比较简单的一道题了,但是考 ...

  8. NOIP模拟96(多校29)

    T1 子集和 解题思路 大概是一个退背包的大白板,然而我考场上想复杂了,竟然还用到了组合数. 但是大概意思是一样的,有数的最小值一定是一个在 \(a\) 数组中存在的数字. 那么我们想办法除去它对应的 ...

  9. NOIP模拟99(多校31)

    T1 法阵 解题思路 原题3100,张口放 T1(出题人原话) 思维题,合法的情况其实就是上下两个梯形拼起来的样子. 他们的边界都是在 \(i\) 轴上面,但是不能相交. 于是我们可以尝试两者相交的纵 ...

  10. 5.23考试总结(NOIP模拟2)

    5.23考试总结(NOIP模拟2) 洛谷题单 看第一题第一眼,不好打呀;看第一题样例又一眼,诶,我直接一手小阶乘走人 然后就急忙去干T2T3了 后来考完一看,只有\(T1\)骗到了\(15pts\)[ ...

随机推荐

  1. redis 简单整理——Lua[十一]

    前言 简单介绍一下Lua. 正文 为了保证多条命令组合的原子性,Redis提供了简单的事务功能以及集 成Lua脚本来解决这个问题. 前面提及到pipline,也提及到pipline 并不是原子性的,如 ...

  2. spring boot 配置文件占位符和多环境配置 [七]

    配置文件占位符 person.last-name=zhangsan person.age=${random.int} person.birth=2017/12/15 person.boss=false ...

  3. FPGA技术脚本使用

    做fpga 不会脚本,基本跟残废一个概念.以前我觉得做FPGA应该学习什么人工智能,大数据,机器人.现在想起来真是傻逼,做fpga也好,做ic,做逻辑其实基本能力都是一样的. 一个学习tcl脚本,pe ...

  4. PyQt 快速使用

    1.安装 PyQt:使用 pip 命令在终端或命令提示符中运行以下命令: pip install pyqt5 2.创建 PyQt 应用程序:导入 PyQt5 模块并创建一个 QApplication ...

  5. HarmonyOS NEXT应用开发案例——自定义TabBar

    介绍 本示例主要介绍了TabBar中间页面如何实现有一圈圆弧外轮廓以及TabBar页签被点击之后会改变图标显示,并有一小段动画效果. 效果图预览 使用说明: 依次点击tabBar页面,除了社区图标之外 ...

  6. ModelScope初探:一行代码调用成熟AI模型。

    简介: 如何用一行代码调用成熟AI模型?试试ModelScope,让AI开发者解放生产力! ModelScope是阿里推出的下一代开源的模型即服务共享平台,为泛AI开发者提供灵活.易用.低成本的一站式 ...

  7. 让容器跑得更快:CPU Burst 技术实践

    ​简介:让人讨厌的 CPU 限流影响容器运行,有时人们不得不牺牲容器部署密度来避免 CPU 限流出现.我们设计的 CPU Burst 技术既能保证容器运行服务质量,又不降低容器部署密度.CPU Bur ...

  8. 无处不在的 Kubernetes,难用的问题解决了吗?

    ​简介: 从第三方的调研数据看,容器和 Kubernetes 已经成为云原生时代主流的选择,但实际落地的时候,却陷入了困境.我们尝试去总结了一些共通点,以及应对方案,也许能为正在落地容器技术的企业提供 ...

  9. Python静态类型解析工具简介和实践

    简介: Python是一门强类型的动态类型语言,开发者可以给对象动态指定类型,但类型不匹配的操作是不被允许的.动态类型帮助开发者写代码轻松愉快,然而,俗话说:动态一时爽,重构火葬场.动态类型也带来了许 ...

  10. [GPT] nodejs 有哪些类似 jquery 语法的 html 解析库

      在Node.js中,有一些类似jQuery语法的HTML解析库可供选择. 以下是其中几个常用的库: 1. Cheerio: Cheerio是一个快速.灵活且易于使用的HTML解析库,它提供了类似于 ...