做题心得
这次考试多多少少还是表现了自己在一些能力的缺失,还是太容易不审清楚题目就放开去做了,这一点不好,比如今天第一题与第三题,第一题真的水,但是自己却因为水而想的过于简单,直接就爆0了,血的教训,第三题是因为自己没有合理地估计答案范围,贪心出来了,但是却少开了long long 导致直接只有40分,改为long long后满分,所以还是得好好反思啊;
解题报告
第一题
设一个含有 n 个数的序列的优雅度为满足 ai< ai+1(1≤ i < n) 的 i 的个数。现在给出一个含有 n 个数的序列,小 X 想要将这 n 个数调整顺序,使得新序列的优雅度最大。同样喜欢优雅的你,能否求出这个最大的优雅度
呢?
输入格式:
第 1 行:一个整数 n
第 2 行:n 个整数,表示原始序列
输出格式:
输出 1 个整数,为新序列的最大优雅度
样例输入
5
1 3 2 4 1
样例输出
3
AC思路
直接上代码吧
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n;
int sum=0;
int a[100055];
int main()
{
//freopen("grace.in","r",stdin);
//freopen("grace.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
sort(a+1,a+n+1);
int now=1;
for(int i=1;i<n;i++)
{
int ans=0;
int u=a[i];
while(a[i]==u)ans++,i++;
now=max(now,ans);
}
cout<<n-now;
}
第二题
如果一个无自环无重边无向连通图的任意一个点最多属于一个简单环,我们就称之为仙人球。所谓简单环即不经过重复的结点的环。现在,小 Z 有一张仙人球图,他想知道两个点之间不同的非复杂路径的条数。这里复杂路径指的是经过某条边至少两次的路径,两条路径不同当且仅当它们之中的边不同。这个问题太难了,所以小 Z 想要请教请教你。当然,为了不让你特别尴尬,你只需要求出条数 mod 1000000007 的值即可
输入格式:
第 1 行:两个整数:n、m,分别代表仙人球图的点数和边数
第 2~m+1 行:每行两个整数 xi、yi,表示 xi 和 yi 之间有一条边
第 m+2 行:一个整数 k,表示询问个数
第 m+3~m+k+2 行:每行两个整数 ai、bi,表示小 G 的询问
输出格式:
输出 k 行,每行一个整数,为 ai 到 bi 的不同的非复杂路径的条数 mod
1000000007 的值。
样例输入
10 11
1 2
2 3
3 4
1 4
3 5
5 6
8 6
8 7
7 6
7 9
9 10
6
1 2
3 5
6 9
9 2
9 3
9 10
样例输出
2
2
2
4
4
1
样例解释
画图易看出询问 1、3、4、6 的答案;询问 2 有两种方案:3->5 和
3->4->1->2->3->5 , 这 里 应 注 意 3->4->1->2->3->5 和
3->2->1->4->3->5 是同一条路径;询问 5 同理。
AC思路
这道题一看就知道是强联通分量缩点建图,然后求经过路径上环的个数(起点终点也算),注意这是求两点间而不是哪一点到哪一点的路径,意味着连这个询问都不是有向的!所以只要统计路上环的个数,再用快速幂乘一下就是了;
但是我们发现,如果一次次循环遍历,绝对会超时,那么就需要找LCA求最短路就可以了,2的个数就是这两个的2的个数减去2倍的LCA的2的个数,但是我们发现,如果LCA是个就环的话,会算不到那个环,所以还要判断一下加回去;
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int n,m,k;
int tot=0,head[200030],belong[200030];
long long shu[200030];
int biao[200030];
int zz=0,hh[200030];
int vis[200005];
int s=0,sum=0,top=0;
int dfs[200030],low[200030],stack[200030];
long long xian[200005],fa[200005];
struct node
{
int f,t,nt;
}e[400030],l[400030];
struct nn
{
int f,t,nt;
long long ans;
}q[400030];
int build(int f,int t)
{
tot++;
e[tot].f=f;
e[tot].t=t;
e[tot].nt=head[f];
head[f]=tot;
}
int build2(int f,int t)
{
zz++;
l[zz].f=f;
l[zz].t=t;
l[zz].nt=hh[f];
hh[f]=zz;
}
int tarjin(int u,int f)
{
s++;
low[u]=dfs[u]=s;
top++;
stack[top]=u;
biao[u]=1;
for(int i=head[u];i;i=e[i].nt)
{
int v=e[i].t;
if(v!=f)
{
if(!dfs[v])
{
tarjin(v,u);
low[u]=min(low[u],low[v]);
}
else if(biao[v])
low[u]=min(low[u],dfs[v]);
}
}
if(low[u]==dfs[u])
{
sum++;
int t=stack[top];
while(t!=u)
{
top--;
belong[t]=sum;
shu[sum]++;
biao[t]=0;
t=stack[top];
}
top--;
belong[u]=sum;
biao[u]=0;
shu[sum]++;
}
}
int getfa(int u)
{
if(fa[u]!=u)fa[u]=getfa(fa[u]);
return fa[u];
}
int yy(int u)
{
fa[u]=u;
biao[u]=1;
if(shu[u]>=2)xian[u]++;
for(int i=hh[u];i;i=l[i].nt)
{
int v=l[i].t;
if(!biao[v])
{
xian[v]=xian[u];
yy(v);
fa[v]=u;
fa[u]=u;
}
}
vis[u]=1;
for(int i=head[u];i;i=q[i].nt)
{
int v=q[i].t;
if(vis[v])
{
int k=getfa(v);
int h=xian[u]+xian[v]-2*xian[k];
//cout<<u<<" "<<v<<" "<<k<<" "<<h<<endl;
if(shu[k]>2)
h++;
//cout<<u<<" "<<v<<" "<<k<<" "<<h<<endl;
int sum=1,l=2;
while(h)
{
if(h%2==1)
{
sum*=l;
sum%=10000007;
}
l=l*l;
l%=10000007;
h=h/2;
}
q[i].ans=sum;
if(i%2==1)q[i+1].ans=q[i].ans;
else q[i-1].ans=q[i].ans;
}
}
}
int bb(int f,int t)
{
tot++;
q[tot].f=f;
q[tot].t=t;
q[tot].nt=head[f];
head[f]=tot;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
build(a,b);
build(b,a);
}
for(int i=1;i<=n;i++)
{
fa[i]=i;
}
tarjin(1,1);
for(int i=1;i<=tot;i+=2)
{
if(belong[e[i].f]!=belong[e[i].t])
{
build2(belong[e[i].f],belong[e[i].t]);
build2(belong[e[i].t],belong[e[i].f]);
}
}
memset(biao,0,sizeof(biao));
memset(head,0,sizeof(head));
cin>>k;
tot=0;
/* for(int i=1;i<=n;i++)
cout<<belong[i]<<" ";*/
for(int i=1;i<=k;i++)
{
int a,b;
scanf("%d%d",&a,&b);
bb(belong[a],belong[b]);
bb(belong[b],belong[a]);
}
yy(1);
for(int i=1;i<=k*2;i+=2)
{
cout<<q[i].ans;
cout<<endl;
}
return 0;
}//真的有些工业。。。
第三题
虽然说是DP,其实很水,贪心就过去了,所以就不写了。。。。。