4489. 最长子序列
题意:给定一个长度为 n n n 的严格单调递增的整数序列 a 1 , a 2 , … , a n a_1,a_2,…,a_n a1,a2,…,an。
序列 a a a 的子序列可以表示为 a i 1 , a i 2 , … , a i p a_{i1},a{i2},…,a{ip} ai1,ai2,…,aip,其中 1 ≤ i 1 < i 2 < … < i p ≤ n 1≤i_1<i_2<…<i_p≤n 1≤i1<i2<…<ip≤n。
我们希望找到一个 a a a 的子序列,使得该子序列满足:对于$ j \in[1,p−1] , , ,a_{i_{j+1}}≤a_{i_{j×2}}$ 恒成立。
我们认为,长度为 1 1 1 的子序列总是满足条件的。
请你计算并输出满足条件的子序列的最大可能长度。
输入格式
第一行包含一个整数 n n n。
第二行包含 n n n 个整数 a 1 , a 2 , … , a n a_1,a_2,…,a_n a1,a2,…,an。
输出格式
一个整数,表示满足条件的子序列的最大可能长度。
直觉:二分答案,但是发现题目中说序列是严格单调递增的,也就是没有重复的元素,所以可以考虑贪心。用类似双指针的思路贪心就行,(细节写的不好,调了一段时间)
/*
A: 10min
B: 20min
C: 30min
D: 40min
*/
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <sstream>
#define pb push_back
#define all(x) (x).begin(),(x).end()
#define mem(f, x) memset(f,x,sizeof(f))
#define fo(i,a,n) for(int i=(a);i<=(n);++i)
#define fo_(i,a,n) for(int i=(a);i<(n);++i)
#define debug(x) cout<<#x<<":"<<x<<endl;
#define endl '\n'
using namespace std;
//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math,O3")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
template<typename T>
ostream& operator<<(ostream& os,const vector<T>&v){for(int i=0,j=0;i<v.size();i++,j++)if(j>=5){j=0;puts("");}else os<<v[i]<<" ";return os;}
template<typename T>
ostream& operator<<(ostream& os,const set<T>&v){for(auto c:v)os<<c<<" ";return os;}
template<typename T1,typename T2>
ostream& operator<<(ostream& os,const map<T1,T2>&v){for(auto c:v)os<<c.first<<" "<<c.second<<endl;return os;}
template<typename T>inline void rd(T &a) {
char c = getchar(); T x = 0, f = 1; while (!isdigit(c)) {if (c == '-')f = -1; c = getchar();}
while (isdigit(c)) {x = (x << 1) + (x << 3) + c - '0'; c = getchar();} a = f * x;
}
typedef pair<long long ,long long >PII;
typedef pair<long,long>PLL;
typedef long long ll;
typedef unsigned long long ull;
const int N=2e5+10,M=1e9+7;
ll n,a[N];
ll ans=1;
void solve(){
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;){
int j = i+1;
int p = i , q = j;
bool flag=0;
while(q<=n && a[q]<=a[p]*2){
p++,q++;
flag=1;
}
if(flag){
// cout<<i<<" "<<q<<endl;
ans = max(ans,(1ll)*(q-i));
}
i = q;
}
cout<<ans;
}
int main(){
solve();
return 0;
}
4490. 染色
给定一个 n n n 个节点的树,节点编号为 1 ∼ n 1∼n 1∼n。
1 1 1 号节点是树的根节点。
初始时,所有节点的颜色均为 0 0 0。
现在,你需要对该树进行重新染色,其中节点 i i i 的目标颜色为 c i c_i ci。
每次染色操作的具体流程如下:
- 选择一个节点 v v v 和一种颜色 x x x。
- 将以节点 v v v 为根节点的子树中的全部节点(包括节点 v v v)都染成颜色 x x x。
请你计算,为了使得每个节点都被染成目标颜色,至少需要进行多少次染色操作。
输入格式
第一行包含整数 n n n。
第二行包含 n − 1 n−1 n−1 个整数 p 2 , p 3 , … , p n p_2,p_3,…,p_n p2,p3,…,pn,其中 p i p_i pi 表示节点 i i i 的父节点编号。
第三行包含 n n n 个整数 c 1 , c 2 , … , c n c_1,c_2,…,c_n c1,c2,…,cn,其中 c i c_i ci 表示节点 i i i 的目标颜色。
保证输入给定图是一棵树。
输出格式
一个整数,表示最少所需的染色操作次数。
所有测试点满足 2 ≤ n ≤ 1 0 4 2≤n≤10^4 2≤n≤104, 1 ≤ p i < i 1≤p_i<i 1≤pi<i, 1 ≤ c i ≤ n 1≤c_i≤n 1≤ci≤n。
直觉:dfs遍历,不是树形dp。
发现如果一个子节点的颜色和他的父节点颜色不同的话,一定会进行一次染色。
从父节点向下染色。首先给的当前遍历到的节点染色,如果该节点染成所需要的颜色后和父节点的颜色相同。那么不需要多一次操作,如果不同表面需要从该节点向下染色。
所以dfs需要传入每次父节点需要染成的颜色,还需要每个节点想变成的颜色,初始颜色。
一开始第一步没有先染色,导致调了一段时间,熟练度不够。
/*
A: 10min
B: 20min
C: 30min
D: 40min
*/
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <sstream>
#define pb push_back
#define all(x) (x).begin(),(x).end()
#define mem(f, x) memset(f,x,sizeof(f))
#define fo(i,a,n) for(int i=(a);i<=(n);++i)
#define fo_(i,a,n) for(int i=(a);i<(n);++i)
#define debug(x) cout<<#x<<":"<<x<<endl;
#define endl '\n'
using namespace std;
//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math,O3")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
template<typename T>
ostream& operator<<(ostream& os,const vector<T>&v){for(int i=0,j=0;i<v.size();i++,j++)if(j>=5){j=0;puts("");}else os<<v[i]<<" ";return os;}
template<typename T>
ostream& operator<<(ostream& os,const set<T>&v){for(auto c:v)os<<c<<" ";return os;}
template<typename T1,typename T2>
ostream& operator<<(ostream& os,const map<T1,T2>&v){for(auto c:v)os<<c.first<<" "<<c.second<<endl;return os;}
template<typename T>inline void rd(T &a) {
char c = getchar(); T x = 0, f = 1; while (!isdigit(c)) {if (c == '-')f = -1; c = getchar();}
while (isdigit(c)) {x = (x << 1) + (x << 3) + c - '0'; c = getchar();} a = f * x;
}
typedef pair<long long ,long long >PII;
typedef pair<long,long>PLL;
typedef long long ll;
typedef unsigned long long ull;
const int N=1e5+10,M=1e9+7;
int h[N],e[N],ne[N],idx;
int n,fa[N];
int pre[N],col[N],ans;
void add(int a,int b){
e[idx]=b;
ne[idx]=h[a];
h[a]=idx++;
}
void dfs(int u,int Fa,int Col){ // 将u节点和他的子树染成col[u]
bool flag=1;
pre[u] = Col;
if(pre[u] != col[u]){ // 当前节点的颜色和需要变成的颜色不同
pre[u] = col[u];
ans++;
if(col[u] == Col){ // 如果需要变成的颜色和祖宗颜色相同
;
}
else{
flag=0;
}
}
for(int i=h[u];~i;i=ne[i]){
int j=e[i];
if(j==Fa)continue;
if(flag){
dfs(j,u,Col);
}
else
dfs(j,u,pre[u]);
}
}
void solve(){
cin>>n;
memset(h,-1,sizeof h);
fa[1]=1;
for(int i=2;i<=n;i++){
cin>>fa[i];
add(i,fa[i]);
add(fa[i],i);
}
for(int i=1;i<=n;i++)cin>>col[i];
dfs(1,-1,col[1]);
cout<<ans+1;
}
int main(){
solve();
return 0;
}