牛客
牛客月赛44
A.深渊水妖
思路:
经典循环内套循环卡边界!!!
直接用简洁的判断在边界上。思路清晰的及时更新边界而不需要暴力的来做,搞出一大堆边界问题。
最后利用变量$ans$来特殊的判断是否存在全升序!!!
AC Code:
#include<bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
typedef long long ll;
typedef pair<int,int>PII;
typedef unsigned long long ull;
const int M=2010;
const int INF=0x3f3f3f3f;
const int mod=1e9+7;
const int N=2e6+10;
int dx[4]={0,1,0,-1};
int dy[4]={-1,0,1,0};
void solve()
{
int n;
cin>>n;
int ans=0;
int lst=1;
vector<int>a(n+1);
for(int i=1;i<=n;i++)
{
cin>>a[i];
if(a[i-1]>a[i])ans=max(ans,a[i-1]-a[lst]),lst=i;
}
ans=max(ans,a[n]-a[lst]);
lst=1;
for(int i=1;i<=n;i++)
{
if(a[i-1]>a[i])
{
if(a[i-1]-a[lst]==ans)cout<<lst<<' '<<i-1<<' ';
lst=i;
}
}
if(ans==a[n]-a[lst])cout<<lst<<' '<<n<<endl;
return;
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
// freopen("test.in","r",stdin);
int t;cin>>t;
while(t--)solve();
return 0;
}
时间复杂度$O(n)$
题意:
1.给定一颗树,定义一种新的路径.求这种路径的数量!!!同时定义了一种新的权值:包含的黑点个数 -− 包含的白点个数。
2.注意这里的树边是无向的!!!
3.根据题目的定义可以发现 黑点白点是重复相间连 相间隔的,也就是任意一条边必定是由一黑一白所组成.
4.而一个点也可以构成一条链.因此这种路径的最大权值必定为1.
5.根据前面的启发就可以得到这种路径一定就是起点为黑点,终点为黑点!!!
6.注意只要起点和终点相同的路径在本题中均认定为同一种路径。
难点:由于数据量较大,因此需要特别注意所有数据的初始化包括:Add函数的idx,和头指针数组以及各种变量!!!
写了一种不使用DFS的算法,但是有问题猜测可能是数据中存在重边,使得染色过程有矛盾。
法一:
无向树的DFS
AC Code:
#include<bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
typedef long long ll;
typedef pair<int,int>PII;
typedef unsigned long long ull;
const int M=2010;
const int INF=0x3f3f3f3f;
const int mod=1e9+7;
const int N=2e6+10;
int dx[4]={0,1,0,-1};
int dy[4]={-1,0,1,0};
ll ans=0;
int e[N],ne[N],idx,h[N];
void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs(int u,int fa,int col)
{
if(col)ans++;
for(int i=h[u];~i;i=ne[i])
{
int j=e[i];
if(j!=fa)dfs(j,u,col^1);//搜索子节点
}
}
void solve()
{
int n;cin>>n;
idx=0;
ans=0;
for(int i=1;i<=n;i++)h[i]=-1;//数据初始化!!!
for(int i=1;i<=n-1;i++)
{
int u,v;
cin>>u>>v;
add(u,v);
add(v,u);
}
dfs(1,1,1);
cout<<ans*(ans-1)/2+ans<<endl;
return ;
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
// freopen("test.in","r",stdin);
int t;cin>>t;
while(t--)solve();
return 0;
}
法2:
可以写成有向树的DFS
AC Code:
#include<bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
typedef long long ll;
typedef pair<int,int>PII;
typedef unsigned long long ull;
const int M=2010;
const int INF=0x3f3f3f3f;
const int mod=1e9+7;
const int N=2e6+10;
int dx[4]={0,1,0,-1};
int dy[4]={-1,0,1,0};
ll ans=0;
int e[N],ne[N],idx,h[N];
bool vis[N];
void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs(int u,int fa,int col)//有向图写法
{
if(col)ans++;
vis[u]=true;
for(int i=h[u];~i;i=ne[i])
{
int j=e[i];
if(!vis[j])dfs(j,u,col^1);//搜索子节点
}
}
void solve()
{
int n;cin>>n;
idx=0;
ans=0;
for(int i=1;i<=n;i++)h[i]=-1;//数据初始化!!!
for(int i=1;i<=n;i++)vis[i]=false;
for(int i=1;i<=n-1;i++)
{
int u,v;
cin>>u>>v;
add(u,v);
add(v,u);
}
dfs(1,1,1);
cout<<ans*(ans-1)/2+ans<<endl;
return ;
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
// freopen("test.in","r",stdin);
int t;cin>>t;
while(t--)solve();
return 0;
}
时间复杂度:$O(n)$