ZJNU 2184 - 最長子串 (並查集)
阿新 • • 發佈:2021-08-13
題面
給出一個長度為\(n\)的數列,\(m\)個詢問。
\(1\ x\):找到\([l,r]\)使得對於所有的\(l\le i\le r\),\(a[i]\ge x\)且\(r-l+1\)最大
\(2\ x\ y\):令\(a[x]=y\)
\(1\lt n\le 10^5,\ 1\lt m\le 10^4,\ 0\le a[i]\le 10^5\)
保證修改的次數不超過\(10\)
思路
修改的次數不超過\(10\)次,可以考慮每次修改後都預處理出所有答案,對於詢問\(O(1)\)處理
對於答案的處理,考慮記錄下每種數字的位置,放在vector中
從大到小處理所有答案,假設當前處理到了值\(x\),先檢查所有值為\(x\)的位置的左右兩側是否值比\(x\)大,如果是則藉助並查集將其合併
那麼值\(x\)的答案也就是此時最大的集合的元素個數
#include<bits/stdc++.h> #define closeSync ios::sync_with_stdio(0);cin.tie(0);cout.tie(0) #define multiCase int T;cin>>T;for(int t=1;t<=T;t++) #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i<(b);i++) #define per(i,a,b) for(int i=(a);i>=(b);i--) #define perr(i,a,b) for(int i=(a);i>(b);i--) #define all(a) (a).begin(),(a).end() #define SUM(a) accumulate(all(a),0LL) #define MIN(a) (*min_element(all(a))) #define MAX(a) (*max_element(all(a))) #define mst(a,b) memset(a,b,sizeof(a)) #define pb push_back #define eb emplace_back #define fi first #define se second using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> pii; const int INF=0x3f3f3f3f; const ll LINF=0x3f3f3f3f3f3f3f3f; const double eps=1e-12; const double PI=acos(-1.0); const ll mod=998244353; const int dx[8]={0,1,0,-1,1,1,-1,-1},dy[8]={1,0,-1,0,1,-1,1,-1}; void debug(){cerr<<'\n';}template<typename T,typename... Args>void debug(T x,Args... args){cerr<<"[ "<<x<< " ] , ";debug(args...);} mt19937 mt19937random(std::chrono::system_clock::now().time_since_epoch().count()); ll getRandom(ll l,ll r){return uniform_int_distribution<ll>(l,r)(mt19937random);} ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);} ll qmul(ll a,ll b){ll r=0;while(b){if(b&1)r=(r+a)%mod;b>>=1;a=(a+a)%mod;}return r;} ll qpow(ll a,ll n){ll r=1;while(n){if(n&1)r=(r*a)%mod;n>>=1;a=(a*a)%mod;}return r;} ll qpow(ll a,ll n,ll p){ll r=1;while(n){if(n&1)r=(r*a)%p;n>>=1;a=(a*a)%p;}return r;} int a[100050]; int n,m; int ans[100050]; int gp[100050],siz[100050]; vector<int> G[100050]; int fnd(int p) { return p==gp[p]?p:(gp[p]=fnd(gp[p])); } int merge(int a,int b) { int ga=fnd(a),gb=fnd(b); if(ga==gb) return 0; if(ga>gb) swap(ga,gb); siz[ga]+=siz[gb]; //記錄集合大小 siz[gb]=0; gp[gb]=ga; return siz[ga]; } void deal() { rep(i,0,100000) G[i].clear(); rep(i,1,n) { gp[i]=i; siz[i]=1; G[a[i]].pb(i); } per(i,100000,0) { ans[i]=ans[i+1]; if(!G[i].empty()) //非空則答案至少為1 ans[i]=max(ans[i],1); for(int p:G[i]) { if(p!=1) { if(a[p-1]>=a[p]) ans[i]=max(ans[i],merge(p-1,p)); } if(p!=n) { if(a[p+1]>=a[p]) ans[i]=max(ans[i],merge(p+1,p)); } } } } void solve() { while(cin>>n>>m) { rep(i,1,n) cin>>a[i]; deal(); rep(i,1,m) { int op; cin>>op; if(op==1) { int x; cin>>x; cout<<ans[x]<<'\n'; } else { int p,x; cin>>p>>x; a[p]=x; deal(); } } } } int main() { closeSync; //multiCase { solve(); } return 0; }