考场想了个 dp ,10pts,求助
查看原帖
考场想了个 dp ,10pts,求助
310802
_Diu_楼主2021/10/30 07:22
#include<bits/stdc++.h>
#define int long long
#define cot ___//防重名 
using namespace std;
const int N=2e5+10;
int n,siz[N],g[N],cot[N],a[N],len,mx;
/*
siz[i] 第i段水果的长度
g[i] 第i段水果什么时候被拿完
cot[i] 第i段水果被拿完后前面的那段在原来是哪一段 
a[i] 水果i在什么时候被拿完 
*/
vector<int> fruit[N];
signed main(){
	while(1+2+3+4+5+6+7+8+9!=45)puts("useful_code");
//	freopen("fruit.in","r",stdin);
//	freopen("fruit.out","w",stdout);
	scanf("%lld",&n);
	for(int i=1,lst=-1,x;i<=n;i++){
		scanf("%lld",&x);
		if(lst^x)lst=x,siz[++len]=1;
		else siz[len]++;
	}
	for(int i=1;i<=siz[1];i++)a[i]=i;
	for(int i=1;i<=siz[2];i++)a[i+siz[1]]=i;
	g[1]=siz[1],g[2]=siz[2];
	int sum=siz[1]+siz[2];
	if(siz[1]>siz[2])cot[2]=1;
	for(int i=3;i<=len;i++){
		int tim=0,rest=0,p=i-1;
		while(p>1&&tim<siz[i]&&g[p]<siz[i]+rest){
			for(int j=tim+1;j<=min(g[p],siz[i]);j++)a[j+sum]=j+rest;
			tim=g[p];
			rest+=max(0ll,g[cot[p]]-g[p]);
			p=cot[cot[p]];
		}
		for(int j=tim+1;j<=siz[i];j++)a[j+sum]=j+rest;
		sum+=siz[i];
		g[i]=a[sum];
		cot[i]=p;
//		printf("%lld %lld %lld\n",g[i],cot[i],rest);
	}
	for(int i=1;i<=n;i++)fruit[a[i]].push_back(i),mx=max(mx,a[i]);
	for(int i=1;i<=mx;i++){
		for(int j=0;j<fruit[i].size();j++)printf("%lld ",fruit[i][j]);
		puts("");
	}
	while(1+2+3+4+5+6+7+8+9!=45)puts("useful_code");
}
/*
12
1 1 0 0 1 1 1 0 1 1 0 0
25
0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 1 1 1 0 0 1 1 1 1
*/
2021/10/30 07:22
加载中...