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. python 多进程jieba分词,高效分词,multiprocessing

    自然语言任务经常使用jieba分词,数据量大时怎么加速,jieba分词不支持使用asyncio异步加速,使用multiprocessing还是可以的 import jieba import jieba ...

  2. asyncio async和await列表推导式实现异步高并发执行

    import asyncio import random import time # 需求:有一个crontab调度器,每隔1秒,拉起1个job,要求这些job可以并发爬取网页 async def c ...

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

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

  4. 【笔记】go语言--Map

    go语言--Map //基本结构,定义 m := map[string] string { "name" : "ccmouse",//这些是无序的,是hashm ...

  5. io_uring vs epoll ,谁在网络编程领域更胜一筹?

    ​简介:从定量分析的角度,通过量化 io_uring 和 epoll 两种编程框架下的相关操作的耗时,来分析二者的性能差异. ​ 本文作者:王小光,「高性能存储技术SIG」核心成员. 背景 io_ur ...

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

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

  7. 深入解析 Dubbo 3.0 服务端暴露全流程

    ​简介: 随着云原生时代的到来,Dubbo 3.0 的一个很重要的目标就是全面拥抱云原生.正因如此,Dubbo 3.0 为了能够更好的适配云原生,将原来的接口级服务发现机制演进为应用级服务发现机制. ...

  8. dotnet 6 已知问题 获取 CultureInfo.NumberFormat 可能抛出 IndexOutOfRangeException 异常

    本文记录一个 dotnet 6 已知问题,准确来说这是一个在 dotnet 5 引入的问题,到 dotnet 6.0.12 还没修.在获取 CultureInfo.NumberFormat 属性时,在 ...

  9. 读书笔记 dotnet 的字符串在内存是如何存放

    本文是读伟民哥翻译的 .NET内存管理宝典 这本书的笔记,我认为读书的过程也需要实践,这样对一知半解的知识也有较为清晰的了解.在阅读到 string 在内存的布局时,我看到 RuntimeHelper ...

  10. python实现打扑克方法

    # 游戏规则:# 一付扑克牌,去掉大小王,每个玩家发3张牌,最后比大小,看谁赢.## 有以下几种牌:# 豹子:三张一样的牌,如3张6.# 同花顺:即3张同样花色的顺子, 如红桃 5.6.7# 顺子:又 ...