1. 程式人生 > 實用技巧 >ICPC World Finals 2019 D - Circular DNA

ICPC World Finals 2019 D - Circular DNA

轉化之後的題意:

給出一個環,每個位置都是一種顏色的左括號或右括號

尋找一個環的切割位置,滿足從這個位置切割之後得到的鏈中,單獨看每一種顏色的括號能夠匹配的顏色種類數最大

輸出最小的切割位置和最大匹配的種類數

單獨看一種顏色的括號

左括號+1,右括號-1

如果一個位置切割之後滿足條件,那麼

要求這種顏色所有的加1減1之和為0

而且是是字首和最小的位置

這個位置直到下一個同顏色的位置之間都可以作為切割點

把所顏色的這些區間找出來即可

複雜度分析

最多一個左括號產生一個區間

所以有O(n)個區間

#include<cstdio>
#include<vector>
#include
<algorithm> using namespace std; #define N 1000005 #define lowbit(x) x&-x struct node { int val,pos; }tmp; vector<node>v[N]; int n,c[N]; int tot[N]; int main() { int x; char cc; scanf("%d",&n); int m=0; for(int i=1;i<=n;++i) { cc=getchar(); cc
=getchar(); scanf("%d",&x); m=max(m,x); tmp.pos=i; if(cc=='s') { tmp.val=1; tot[x]++; } else { tmp.val=-1; tot[x]--; } v[x].push_back(tmp); } int len; int mi,l,r,now;
for(int i=1;i<=m;++i) { len=v[i].size(); if(!len || tot[i]) continue; now=0; mi=0; for(int j=0;j<len;++j) { now+=v[i][j].val; if(now<mi) mi=now; } now=0; if(now==mi) { c[1]++; c[v[i][0].pos+1]--; } for(int j=0;j<len;++j) { now+=v[i][j].val; if(now==mi) { c[v[i][j].pos+1]++; if(j!=len-1) c[v[i][j+1].pos+1]--; } } } int mx=-1,ans=0; for(int i=1;i<=n;++i) { now+=c[i]; if(now>mx) { mx=now; ans=i; } } printf("%d %d",ans,mx); }