A-262144(想法)

    科技2022-07-15  119

    题意:

    给出一个数组,每次可以选择相邻的两个相同的数字X变为X+1,求最终数组中最大的数字。

    解析:

    从最小的数开始做(第一次做1,第二次做2……),如果有连续的偶数个就直接合并( 1111 → 22 1111\to22 111122),奇数个可能往两边连所以可以( 11111 → 22122 11111\to22122 1111122122

    代码:

    #include <bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=a;i<=b;i++) #define per(i,a,b) for(int i=a;i>=b;i--) const int maxn=5e5+9; const int MAXN=3e5+9; typedef long long ll; set<int>pos,ps[66]; int a[MAXN]; inline int read() { char ch=getchar(); while(ch==' '||ch=='\n')ch=getchar(); int x=ch-'0';ch=getchar(); while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return x; } void work() { int n=read(); for(int i=1;i<=n;i++) { a[i]=read(); pos.insert(i); ps[a[i]].insert(i); } int ans=0; for(int i=1;i<=61;i++) { vector<int>lef;//printf("I: %d\n",i); while(!ps[i].empty()) { ans=i; int x=*ps[i].begin(); ps[i].erase(x); auto it=pos.find(x); vector<int>ve;ve.push_back(*it); auto nt=it;nt++;pos.erase(it); it=nt;int cnt=1; while(it!=pos.end()) { // printf("it %d\n",*it); if(a[*it]!=i) { break; } // printf("I: %d!!!\n",i); cnt++; ve.push_back(*it); auto nxt=it;++nxt; ps[i].erase(*it); pos.erase(it); it=nxt; } if(cnt%2) { for(int x=0;x<cnt/2;x++)pos.insert(ve[x]),ps[i+1].insert(ve[x]),a[ve[x]]=i+1; for(int x=cnt/2+1;x<ve.size();x++)pos.insert(ve[x]),ps[i+1].insert(ve[x]),a[ve[x]]=i+1; pos.insert(ve[cnt/2]); } else { for(int x=0;x<cnt/2;x++)pos.insert(ve[x]),ps[i+1].insert(ve[x]),a[ve[x]]=i+1; } } } printf("%d\n",ans); } int main(){ //ios::sync_with_stdio(false); cin.tie(0); work(); }
    Processed: 0.566, SQL: 8