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. c# 泛型原理(旧)

    前言 说起泛型可能很多人刚才看到的时候肯定会说牛逼啊,厉害啊,这东西少写了不少代码,我总结了泛型的一个优点,那就是少写代码,额,专业点吧. 优点:增加代码的重复利用率,代码重用. 先不讲原理吧,来讲下 ...

  2. WP/C#实现图像滤镜优化方案:打造炫目视觉体验!

    原因:我之所以想做这个项目,是因为在之前查找关于C#/WPF相关资料时,我发现讲解图像滤镜的资源非常稀缺.此外,我注意到许多现有的开源库主要基于CPU进行图像渲染.这种方式在处理大量图像时,会导致CP ...

  3. Linux下的权限(角色,文件权限)

    目录 1.什么是权限 2.文件类型及权限 ①Linux文件类型: ②剩余9个字符对应的含义: ③文件权限值的表示方法(进制法) 3.如何操作权限 3.1改变权限的命令操作 chmod #change ...

  4. 阿里开源自研工业级稀疏模型高性能训练框架 PAI-HybridBackend

    ​简介:近年来,随着稀疏模型对算力日益增长的需求, CPU集群必须不断扩大集群规模来满足训练的时效需求,这同时也带来了不断上升的资源成本以及实验的调试成本.为了解决这一问题,阿里云机器学习PAI平台开 ...

  5. KubeVela:标准化的云原生平台构建引擎

    简介: 本文由"GO 开源说"第三期 KubeVela 直播内容修改整理而成,视频内容较长,本文内容有所删减和重构. KubeVela 的背景 KubeVela 是一个基于 Go ...

  6. 贾扬清演讲实录:一个AI开发者的奇幻漂流

    ​简介:2021阿里灵杰AI工程化峰会,贾扬清深度解读阿里灵杰大数据和AI一体化平台. 演讲人:贾扬清 演讲主题:一个AI开发者的奇幻漂流 活动:2021阿里灵杰AI工程化峰会 对于绝大多数人来说,这 ...

  7. 使用AirFlow调度MaxCompute

    简介: airflow是Airbnb开源的一个用python编写的调度工具,基于有向无环图(DAG),airflow可以定义一组有依赖的任务,按照依赖依次执行,通过python代码定义子任务,并支持各 ...

  8. 如何将一棵LSM-Tree塞进NVM

    ​简介: 随着非易失内存产品的商业化推广,我们对于其在云原生数据库中大规模推广的潜力越来越有兴趣.X-Engine是阿里云数据库产品事业部PolarDB新型存储引擎团队研发的一个LSM-tree存储引 ...

  9. RAG 工具和框架介绍: Haystack、 LangChain 和 LlamaIndex

    Haystack. LangChain 和 LlamaIndex,以及这些工具是如何让我们轻松地构建 RAG 应用程序的? 我们将重点关注以下内容: Haystack LangChain LlamaI ...

  10. [Go] golang 替换组件包 更新 go.mod, go.sum 的方式

    当我们不再使用某个包,或者包名变更时,是如何保证 go.mod 更新的. 只要代码中没有地方 import 使用到某个包了,我们运行: $ go mod tidy module 管理器会帮我们自动清理 ...