随机跳题挑战总结 Part4
前言
这次挑战除了和外,还加了一个。
哦对还有一个bigvegetablechicken
这次是跳1蓝1紫1黑。
然而我的三道题都是最水的。亿秒钟秒切
博客链接待添加。
题目
T1T2T3的码长都很短,T3黑题有的题解,写的超级详细,然后很快就懂了。
这好像是我第一次在随机跳题挑战中没有换题诶。
看来还是太菜了,遇到好多题都不会。
题解
T1
一开始没有什么思路,想搞一个的时空复杂度。结果放弃了
还说这道题很简单,要不是他提醒我我都不会做
思路就是把模数分成两边询问,就直接回答,否则就暴力回答。
难度☆☆☆,但是转过弯来就很简单。
T2
一道思维相对简单的贪心,用优先队列维护一下即可。
代码长度也很短,粗略证明了贪心的正确性就行了。
难度☆☆,主要是在贪心的方面思考,可能会想成
T3
大佬的题解 ,里面写的真的非常非常非常好。
一道码量不长但是很有思维难度的题目。
两遍树形即可。中间很多细节都值得思考的。
难度☆☆☆☆☆
代码
T1
#include <cmath>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N=150010,M=410;
int n,m,T,x,y,a[N],cnt[M][M];
char ch;
int main()
{
scanf("%d%d",&n,&m);
T=sqrt(n);
if (T*T<n) T++;
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
for (int j=1;j<=T;j++)
cnt[j][i%j]+=a[i];
}
while (m--)
{
while (ch=getchar()) if (ch=='A'||ch=='C') break;
if (ch=='A')
{
scanf("%d%d",&x,&y);
if (x<=T) printf("%d\n",cnt[x][y]);
else
{
int ans=0;
for (int i=y;i<N;i+=x)
ans+=a[i];
printf("%d\n",ans);
}
}
else
{
scanf("%d%d",&x,&y);
for (int j=1;j<=T;j++)
cnt[j][x%j]-=a[x];
a[x]=y;
for (int j=1;j<=T;j++)
cnt[j][x%j]+=a[x];
}
}
return 0;
}
T2
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define mp make_pair
using namespace std;
const int N=100010;
int n,m,tot,ans,sum,a[N],b[N],last[N],next[N];
priority_queue<pair<int,int> > q;
bool inque[N];
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
b[i]=a[i];
}
sort(b+1,b+1+n);
tot=unique(b+1,b+1+n)-b-1;
for (int i=1;i<=n;i++)
a[i]=lower_bound(b+1,b+1+tot,a[i])-b;
memset(last,0x3f3f3f3f,sizeof(last));
for (int i=n;i>=1;i--)
{
next[i]=last[a[i]];
last[a[i]]=i;
}
for (int i=1;i<=n;i++)
{
if (ans<m && !inque[a[i]])
{
ans++;
inque[a[i]]=1;
}
else if (ans>=m && !inque[a[i]])
{
ans++;
inque[a[i]]=1;
inque[q.top().second]=0;
q.pop();
}
q.push(mp(next[i],a[i]));
}
printf("%d\n",ans);
return 0;
}
T3
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long ll;
const int N=100010;
const ll Inf=1e17;
int n,m,tot,head[N];
ll f[N][3],g[N][15][3],MOD;
struct edge
{
int next,to;
}e[N*2];
void add(int from,int to)
{
e[++tot].to=to;
e[tot].next=head[from];
head[from]=tot;
}
void dp1(int x,int fa)
{
f[x][0]=1; f[x][1]=Inf; f[x][2]=Inf;
for (int i=head[x];~i;i=e[i].next)
{
int y=e[i].to;
if (y!=fa)
{
dp1(y,x);
f[x][2]=min(max(f[x][2],f[y][2]+1),max(f[x][1],f[y][1]));
f[x][1]=min(max(f[x][1],f[y][2]+1),max(f[x][0],f[y][1]));
f[x][0]=max(f[x][0],f[y][2]+1);
}
}
f[x][1]=min(f[x][1],f[x][0]);
f[x][2]=min(f[x][2],f[x][1]);
}
void dp2(int x,int fa)
{
for (int i=1;i<=f[1][2];i++)
g[x][i][0]=1;
for (int i=head[x];~i;i=e[i].next)
{
int y=e[i].to;
if (y!=fa)
{
dp2(y,x);
for (int j=1;j<=f[1][2];j++)
{
g[x][j][2]=(g[x][j][2]*g[y][j-1][2]+g[x][j][1]*g[y][j][1])%MOD;
g[x][j][1]=(g[x][j][1]*g[y][j-1][2]+g[x][j][0]*g[y][j][1])%MOD;
g[x][j][0]=(g[x][j][0]*g[y][j-1][2])%MOD;
}
}
}
for (int i=1;i<=f[1][2];i++)
{
g[x][i][1]=(g[x][i][1]+g[x][i][0])%MOD;
g[x][i][2]=(g[x][i][2]+g[x][i][1])%MOD;
}
}
int main()
{
memset(head,-1,sizeof(head));
scanf("%d%d%lld",&n,&m,&MOD);
if (m!=n-1) return !printf("-1\n-1");
for (int i=1,x,y;i<=m;i++)
{
scanf("%d%d",&x,&y);
add(x,y); add(y,x);
}
dp1(1,0);
dp2(1,0);
printf("%lld\n%lld",f[1][2]-1,g[1][f[1][2]][2]);
return 0;
}
总结
我太菜了。