[DP || 贪心 链表] BZOJ 4576 [Usaco2016 Open]262144 & BZOJ 4580 [Usaco2016 Open]248
2016-10-23 12:14
513 查看
有意思的一道题
官网上的做法是f[i][j]表示从j出发能够合并出i的末端 不存在则为0
然后就可以转移了
这有什么好呢 短
或者可以直接贪心 用链表维护
把能连续偶数个合并的直接合并
要是是奇数个的话 把链断开 合并后两边都分到新的这个块
虽说复杂度官网上说是nlogn 但实际表现很好
还有用单调栈维护贪心的:http://blog.csdn.net/aarongzk/article/details/51712701
官网上的做法是f[i][j]表示从j出发能够合并出i的末端 不存在则为0
然后就可以转移了
这有什么好呢 短
#include<cstdio> #include<cstdlib> #include<algorithm> using namespace std; inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; } return *p1++; } inline void read(int &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); } const int N=300005; int n,a ; int f[105] ; int main(){ int ans=0; freopen("two.in","r",stdin); freopen("two.out","w",stdout); read(n); for (int i=1;i<=n;i++) read(a[i]); for (int i=1;i<=70;i++) for (int j=1;j<=n;j++){ f[i][j]=a[j]==i?j:(f[i-1][j]?f[i-1][f[i-1][j]+1]:0); if (f[i][j]) ans=max(ans,i); } printf("%d\n",ans); return 0; }
或者可以直接贪心 用链表维护
把能连续偶数个合并的直接合并
要是是奇数个的话 把链断开 合并后两边都分到新的这个块
虽说复杂度官网上说是nlogn 但实际表现很好
#include<cstdio> #include<cstdlib> #include<algorithm> #include<vector> using namespace std; typedef pair<int,int> abcd; inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; } return *p1++; } inline void read(int &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } const int N=300005; const int M=500005; int n,ans,a ; int pre[M],nxt[M]; abcd A[M]; int cnt; int del[M]; vector<int> Vec[105]; inline void Solve(int x){ if (del[x]) return; int Pre=pre[x],Nxt=nxt[x]; if (A[x].second==1){ if (Pre) nxt[Pre]=0; if (Nxt) pre[Nxt]=0; }else if (~A[x].second&1){ A[x]=abcd(A[x].first+1,A[x].second>>1); ans=max(ans,A[x].first); while (Pre && A[Pre].first==A[x].first) del[Pre]=1,A[x].second+=A[Pre].second,Pre=pre[Pre]; while (Nxt && A[Nxt].first==A[x].first) del[Nxt]=1,A[x].second+=A[Nxt].second,Nxt=nxt[Nxt]; pre[x]=Pre; if (Pre) nxt[Pre]=x; nxt[x]=Nxt; if (Nxt) pre[Nxt]=x; Vec[A[x].first].push_back(x); }else{ A[x]=A[++cnt]=abcd(A[x].first+1,A[x].second>>1); ans=max(ans,A[x].first); while (Pre && A[Pre].first==A[x].first) del[Pre]=1,A[x].second+=A[Pre].second,Pre=pre[Pre]; while (Nxt && A[Nxt].first==A[cnt].first) del[Nxt]=1,A[cnt].second+=A[Nxt].second,Nxt=nxt[Nxt]; pre[x]=Pre; nxt[x]=0; if (Pre) nxt[Pre]=x; nxt[cnt]=Nxt; pre[cnt]=0; if (Nxt) pre[Nxt]=x; Vec[A[x].first].push_back(x); Vec[A[x].first].push_back(cnt); } } int main(){ freopen("two.in","r",stdin); freopen("two.out","w",stdout); read(n); for (int i=1;i<=n;i++){ read(a[i]); ans=max(ans,a[i]); if (a[i]!=a[i-1]) A[++cnt]=abcd(a[i],1); else A[cnt].second++; } for (int i=1;i<=cnt;i++) Vec[A[i].first].push_back(i),pre[i]=i-1,nxt[i]=i+1; pre[1]=0; nxt[cnt]=0; for (int i=1;i<=70;i++) for (int j=0;j<(signed)Vec[i].size();j++) Solve(Vec[i][j]); printf("%d\n",ans); return 0; }
还有用单调栈维护贪心的:http://blog.csdn.net/aarongzk/article/details/51712701
相关文章推荐
- 【BZOJ4576】【BZOJ4580】【Usaco2016 Open】262144 贪心
- 【BZOJ4580】[Usaco2016 Open]248【区间DP】【或 贪心】
- BZOJ4580: [Usaco2016 Open]248 dp
- [BZOJ4580][Usaco2016 Open]248(dp)
- bzoj 4580: [Usaco2016 Open]248 (dp)
- 【bzoj4580】[Usaco2016 Open]248 区间dp
- bzoj 4580: [Usaco2016 Open]248
- BZOJ4580 [Usaco2016 Open]248
- 【BZOJ 4580】【Usaco2016 Open】248
- BZOJ 4580: [Usaco2016 Open]248
- BZOJ4580: [Usaco2016 Open]248
- 【BZOJ4582】【Usaco2016 open】Diamond Collector 贪心
- 4580: [Usaco2016 Open]248
- BZOJ 2097 USACO 2010 Dec Gold Exercise 奶牛健美操 二分答案 树形DP 贪心
- [BZOJ1688][Usaco2005 Open]Disease Manangement 疾病管理(状压dp)
- [BZOJ 4096] Usaco2013 dec Milk Scheduling · 贪心
- bzoj4576 [Usaco2016 Open]262144
- 【bzoj1616】【Usaco2008 Mar】Cow Travelling (dp)题解&代码
- 【bzoj1617】【Usaco2008 Mar】River Crossing (dp)题解&代码
- 贪心-BZOJ-1623-[Usaco2008 Open]Cow Cars 奶牛飞车