双向链表做法,调了三天了,TLE #8、9,救救孩子吧QAQ
查看原帖
双向链表做法,调了三天了,TLE #8、9,救救孩子吧QAQ
510555
ImposterAnYu楼主2022/7/1 19:45
#include<bits/stdc++.h>
#define int1 long long
//#define p 1145141919810114514
using namespace std;
int1 n,m,i,y = -1,x,head = 1,nex[200005],l[200005],b[200005],bb[200005],v;
vector<int1> a[200005];
int1 read(){//快读。 
	int1 x = 0,f = 1;
	char ch = getchar();
	while(!isdigit(ch)){
		if(ch == '-'){
			f = -1;
		}
		ch = getchar();
	}
	while(isdigit(ch)){
		x = (x << 1) + (x << 3) + ch - '0';
		ch = getchar();
	}
	return x * f;
}
void print(int1 x){//快写。 
  	if(x < 0){
    	putchar('-');
    	x = -x;
  	}
  	if(x > 9){
    	print(x / 10);
  	}
  	putchar(x % 10 + 48);
  	return ;
}

int main(){
	//freopen("114514.in","r",stdin);
	//freopen("114514.out","w",stdout);
	n = read();
	for(i = 1; i <= n; i++){
		x = read();
		if(x != y){//存新的块。 
			m++;
			l[m] = m - 1,nex[l[m]] = m;//双向指针。l数组指前一个块的编号,nex数组指后一个块的编号。 
		}
		a[m].push_back(i);
		bb[m]++;
		y = x;
	}
	while(m){
		for(i = head,v = i - 1; i; i = nex[i]){//取水果。 
			if(!((i - v) & 1)){
				continue;
			}
			v = i;
            b[i]++;
			print(a[i][b[i] - 1]);
			putchar(' ');
			if(b[i] == bb[i]){//如果一个块被取完了, 
				if(i == head){
					head = nex[head];//如果表头被取完,就更换表头。 
				}
				nex[l[i]] = nex[i],l[nex[i]] = l[i],m--;//删除块。 
			}
		}
		putchar('\n');
	}
  	return 0;
}

这个代码看上去时间复杂度是 O(n)O(n) 的,因为每个水果只会在被取出时扫一遍。但第 88 个点 nn 只有 2×1052 \times 10^5,这份代码却跑了 7s7s 多,到底为什么啊……

2022/7/1 19:45
加载中...