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. 分布式文件存储-FastDFS

    1.1 FastDFS简介 1.1.1 FastDFS体系结构 FastDFS是一个开源的轻量级分布式文件系统,它对文件进行管理,功能包括:文件存储.文件同步.文件访问(文件上传.文件下载)等,解决了 ...

  2. 【笔记】go语言--切片的操作

    go语言--切片的操作 接上篇切片的概念开始 //Slice添加元素 arr := [...]int{0,1,2,3,4,5,6,7} s1 := arr[2:6] s2 := s1[3:5]//[5 ...

  3. 携手数字人、数字空间、XR平台,阿里云与伙伴共同建设“新视界”

    ​简介:2022阿里云视觉计算私享会:加速虚拟与现实的交互. 引言:2022年互联网行业里XR.数字孪生.虚拟现实等领域再次"翻红".新旧概念频出,不少人相信这些技术将给当下的互联 ...

  4. 开源 1 年半 star 破 1.2 万的 Dapr 是如何在阿里落地的?

    简介: Dapr 是 2019 年 10 月微软开源的可移植.事件驱动分布式运行时,它使开发人员能够轻松地构建运行在云平台和边缘的弹性而微服务化的无状态和有状态的应用程序,从而降低基于微服务架构构建现 ...

  5. 基于 KubeVela 的 GitOps 交付

    ​简介: KubeVela 是一个简单.易用.且高可扩展的云原生应用管理和交付平台,KubeVela 背后的 OAM 模型天然解决了应用构建过程中对复杂资源的组合.编排等管理问题,同时也将后期的运维策 ...

  6. ARMv9刷屏 —— 号称十年最大变革,Realm机密计算技术有什么亮点?

    ​简介: 让我们看下ARMv9机密计算相关的新特性Realm. ​ ARMv9的新闻刷屏了.ARMv9号称十年以来最重大变革,因此让我们看下ARMv9中机密计算相关的新特性Realm.(注:本文是对I ...

  7. Go 调用 Java 方案和性能优化分享

    ​简介: 一个基于 Golang 编写的日志收集和清洗的应用需要支持一些基于 JVM 的算子. ​ 作者 | 响风 来源 | 阿里技术公众号 一 背景 一个基于 Golang 编写的日志收集和清洗的应 ...

  8. 2018-4-15-WPF-在-Alt+Tab-隐藏窗口

    title author date CreateTime categories WPF 在 Alt+Tab 隐藏窗口 lindexi 2018-04-15 10:13:40 +0800 2018-3- ...

  9. Visual Studio 2019 自带混淆工具DotFuscator不需要去网络下载

    http://t.zoukankan.com/daizhipeng-p-13492298.html 大家是否还在困扰发布的项目dll容易被人反编译呢,VS2019默认是没有安装DotFuscator的 ...

  10. [ABC345D] Tiling 位运算の极致运用

    [ABC345D] Tiling 原题解地址:Editorial by Kiri8128 神写法. 将 \(H \times W\) 的网格展开为 \(H \times (W + 1)\) 的序列, ...