#include<iostream>
#include<algorithm>
#include<string.h>
#include<stack>
#include<set>
using namespace std;
#define N 10000002
struct node
{
char ch;
int pos,num,pre,next;
friend bool operator<(node a,node b)
{
if(a.num==b.num)
return a.pos<b.pos;
else
return a.num>b.num;
}
};
struct sun
{
int pos,pre,next;
};
node dia[N+1],tt,pp;
char s[N+1];
set<node> S;
set<node>::iterator it;
sun G[N+1],R[N+1],B[N+1];
int gn,rn,bn,cnt;
void print(int num)
{
int i,j;
for(i=0;i<num;i++)
cout<<dia[i].ch<<dia[i].num<<endl;
}
void init()
{
int i;
for(i=1;i<gn;i++)
G[i-1].next=i;
G[gn-1].next=N;
for(i=1;i<rn;i++)
R[i-1].next=i;
R[rn-1].next=N;
for(i=1;i<bn;i++)
B[i-1].next=i;
B[bn-1].next=N;
}
int finds(sun ri[],int num,int end)
{
int low=0,high=num-1,mid;
while(low<high)
{
mid=(low+high)>>1;
if(ri[mid].pos==end)
return mid;
else if(ri[mid].pos<end)
low=mid+1;
else
high=mid-1;
}
}
int main()
{
int i,n,temp,end,fuck;
char ch;//int test=0;
stack<int>res;
while(scanf("%s",s)!=EOF)
{//while(test);test++;
n=strlen(s);
gn=rn=bn=cnt=0;
for(i=0;i<n;i++)
{
ch=s[i];
temp=i;
if(ch=='G')
{
if(gn==0)
G[gn].pre=-1;
else
G[gn].pre=gn-1;
G[gn++].pos=i;
}
else if(ch=='R')
{
if(rn==0)
R[rn].pre=-1;
else
R[rn].pre=rn-1;
R[rn++].pos=i;
}
else
{
if(bn==0)
B[bn].pre=-1;
else
B[bn].pre=bn-1;
B[bn++].pos=i;
}
while(i+1<n&&s[i+1]==s[temp])
{
i++;
if(ch=='G')
{
G[gn].pre=gn-1;
G[gn++].pos=i;
}
else if(ch=='R')
{
R[rn].pre=rn-1;
R[rn++].pos=i;
}
else
{
B[bn].pre=bn-1;
B[bn++].pos=i;
}
}
dia[cnt].pos=i;
dia[cnt].num=i-temp+1;
dia[cnt].ch=ch;
dia[cnt].pre=cnt-1;
dia[cnt].next=cnt+1;
S.insert(dia[cnt]);
cnt ++;
}
init();
//print(cnt);
int now,start;
while(S.size()!=0)
{
it=S.begin();
end=(*it).pos;
ch=(*it).ch;
temp=(*it).num;
if(temp==1)
break;
if(ch=='G')
{
printf("G");
end=finds(G,gn,end);
start=G[end].next;
for(i=end;temp!=0;i=G[i].pre)
{
temp--;
res.push(i);
}
if(i!=-1)
G[i].next=start;
if(start!=N)
G[start].pre=i;
while(!res.empty())
{
now=res.top();
res.pop();
printf(" %d",G[now].pos+1);
}
printf("/n");
}
else if(ch=='R')
{
printf("R");
end=finds(R,rn,end);
start=R[end].next;
for(i=end;temp!=0;i=R[i].pre)
{
temp--;
res.push(i);
}
if(i!=-1)
R[i].next=start;
if(start!=N)
R[start].pre=i;
while(!res.empty())
{
now=res.top();
res.pop();
printf(" %d",R[now].pos+1);
}
printf("/n");
}
else
{
printf("B");
end=finds(B,bn,end);
start=B[end].next;
for(i=end;temp!=0;i=B[i].pre)
{
temp--;
res.push(i);
}
if(i!=-1)
B[i].next=start;
if(start!=N)
B[start].pre=i;
while(!res.empty())
{
now=res.top();
res.pop();
printf(" %d",B[now].pos+1);
}
printf("/n");
}
if((*it).next!=cnt&&(*it).pre!=-1)
{
tt=dia[(*it).next];
pp=dia[(*it).pre];
S.erase(tt);
S.erase(pp);
if(tt.ch==pp.ch)
{
tt.pre=pp.pre;
tt.num+=pp.num;
if(pp.pre!=-1)
{
fuck=pp.pre;
pp=dia[fuck];
S.erase(pp);
dia[fuck].next=(*it).next;
S.insert(dia[fuck]);
}
dia[(*it).next]=tt;
S.insert(tt);
}
else
{
dia[(*it).next].pre=(*it).pre;
S.insert(dia[(*it).next]);
dia[(*it).pre].next=(*it).next;
S.insert(dia[(*it).pre]);
}
}
else
{
if((*it).next==cnt&&(*it).pre!=-1)
{
pp=dia[(*it).pre];
S.erase(pp);
pp.next=cnt;
dia[(*it).pre].next=cnt;
S.insert(pp);
}
if((*it).next!=cnt&&(*it).pre==-1)
{
tt=dia[(*it).next];
S.erase(tt);
tt.pre=-1;
dia[(*it).next].pre=-1;
S.insert(tt);
}
}
S.erase(*it);
}
S.clear();
}
return 0;
}
先说说思路吧:
给定一串字符串 GRRBBBRRGB,从左边起选出最长的连续子串,如这个子串长度为0,直接退出。否则,将子串删除,若子串不在两端,
则要把剩下的两段合并起来作为新的母串,并返回循环,很显然我们只要开个结构体,在预处理的时候把连在一起的作为一份子,记录个数和
终点(或者起点位置),并记录下相邻的编号,若是第一个,则它的前面编号可以定-1,如是最后一个,则它的后继可以定无穷,然后重载下<号,以个数大为优先,个数一样情况下终点(起点)位置在前优先;然后每次从堆里取出最优的,并处理取出后调整的新情况。
一:若取出的是在两端,(是新串的第一个,即前继为-1,则把它的后继的前继变为-1,若是最后一个,情况类同处理)
二:若取出的是在中间,则分两种情况(1,若它的前继和它的后继是同一个字母,则合并,一点很重要,不要忘记前继的前继的后继将会变成当前取出的后继(倘若前继的前继不是-1),并把它的前继的位置给标记掉。2若它的前继和它的后继不是同一个字母,那只要改变下前继的后继变成它的后继,它的后继的前继变成我的前继)并把更新过的都要重新放回堆里面。堆里面那些垃圾(就是不是最新的信息是不能用的)。
原本打算用set做的,因为中途要不断更改信息,想把错误的信息中set里面删除,但是频繁的删除插入的效果就不在等价于log2(n)了,于是
悲剧诞生了。
后面采用了优先队列,不采取删除,采取标记和比较,若弹出的信息不是最新的就直接pop;然后就是照上面思路YY一下就行了。
Problem: 3476 | User: hd_james | |
Memory: 71340K | Time: 1750MS | |
Language: C++ | Result: Accepted |
#include<iostream>
#include<algorithm>
#include<string.h>
#include<stack>
#include<set>
#include<queue>
using namespace std;
#define N 10000002
struct node
{
char ch;
int pos,num,pre,next,loc;
friend bool operator<(node a,node b)
{
if(a.num==b.num)
return a.pos>b.pos;
else
return a.num<b.num;
}
};
struct sun
{
int pos,pre,next;
};
node dia[N+1],tt,pp;
char s[N+1];
//set<node> S;
node it;
priority_queue<node> Q;
sun G[N+1],R[N+1],B[N+1];
int gn,rn,bn,cnt,res[N+1];
bool flag[N+1];
// void print(int num)
// {
// int i,j;
// for(i=0;i<num;i++)
// cout<<dia[i].ch<<dia[i].num<<endl;
// }
void init()
{
int i;
for(i=1;i<gn;i++)
G[i-1].next=i;
G[gn-1].next=N;
for(i=1;i<rn;i++)
R[i-1].next=i;
R[rn-1].next=N;
for(i=1;i<bn;i++)
B[i-1].next=i;
B[bn-1].next=N;
}
int finds(sun ri[],int num,int end)
{
int low=0,high=num-1,mid;
while(low<=high)
{
mid=(low+high)>>1;
if(ri[mid].pos==end)
return mid;
else if(ri[mid].pos<end)
low=mid+1;
else
high=mid-1;
}
}
int main()
{
int i,n,temp,end,fuck;
char ch;//int test=0;
int cao=0;
// freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
scanf("%s",s);
//gets(s);
{//while(test);test++;
memset(flag,false,sizeof(flag));
n=strlen(s);
gn=rn=bn=cnt=0;
for(i=0;i<n;i++)
{
ch=s[i];
temp=i;
if(ch=='G')
{
if(gn==0)
G[gn].pre=-1;
else
G[gn].pre=gn-1;
G[gn++].pos=i;
}
else if(ch=='R')
{
if(rn==0)
R[rn].pre=-1;
else
R[rn].pre=rn-1;
R[rn++].pos=i;
}
else
{
if(bn==0)
B[bn].pre=-1;
else
B[bn].pre=bn-1;
B[bn++].pos=i;
}
while(i+1<n&&s[i+1]==s[temp])
{
i++;
if(ch=='G')
{
G[gn].pre=gn-1;
G[gn++].pos=i;
}
else if(ch=='R')
{
R[rn].pre=rn-1;
R[rn++].pos=i;
}
else
{
B[bn].pre=bn-1;
B[bn++].pos=i;
}
}
dia[cnt].pos=i;
dia[cnt].num=i-temp+1;
dia[cnt].ch=ch;
dia[cnt].pre=cnt-1;
dia[cnt].next=cnt+1;
dia[cnt].loc=cnt;
//S.insert(dia[cnt]);
Q.push(dia[cnt]);
cnt ++;
}
init();
//print(cnt);
int now,start;
while(!Q.empty())
{
it=Q.top();
Q.pop();
end=it.pos;
ch=it.ch;
temp=it.num;
if(temp==1)
break;
if(flag[end])
continue;
if(dia[it.loc].pre!=it.pre||dia[it.loc].next!=it.next||dia[it.loc].num!=it.num)
continue;
if(ch=='G')
{
printf("G");
end=finds(G,gn,end);
start=G[end].next;
cao=0;
for(i=end;temp!=0;i=G[i].pre)
{
temp--;
//res.push(i);
res[cao++]=i;
}
if(i!=-1)
G[i].next=start;
if(start!=N)
G[start].pre=i;
for(i=cao-1;i>=0;i--)
{
now=res[i];
flag[G[now].pos]=true;
printf(" %d",G[now].pos+1);
}
printf("/n");
}
else if(ch=='R')
{
printf("R");
end=finds(R,rn,end);
start=R[end].next;
cao=0;
for(i=end;temp!=0;i=R[i].pre)
{
temp--;
//res.push(i);
res[cao++]=i;
}
if(i!=-1)
R[i].next=start;
if(start!=N)
R[start].pre=i;
for(i=cao-1;i>=0;i--)
{
now=res[i];
flag[R[now].pos]=true;
printf(" %d",R[now].pos+1);
}
printf("/n");
}
else
{
printf("B");
end=finds(B,bn,end);
start=B[end].next;
cao=0;
for(i=end;temp!=0;i=B[i].pre)
{
temp--;
//res.push(i);
res[cao++]=i;
}
if(i!=-1)
B[i].next=start;
if(start!=N)
B[start].pre=i;
for(i=cao-1;i>=0;i--)
{
now=res[i];
flag[B[now].pos]=true;
printf(" %d",B[now].pos+1);
}
printf("/n");
}
if(it.next!=cnt&&it.pre!=-1)
{
tt=dia[it.next];
pp=dia[it.pre];
//S.erase(tt);
//S.erase(pp);
if(tt.ch==pp.ch)
{
tt.pre=pp.pre;
tt.num+=pp.num;
dia[tt.loc]=tt;
Q.push(tt);
if(pp.pre!=-1)
{
flag[pp.pos]=true;
fuck=pp.pre;
pp=dia[fuck];
dia[fuck].next=it.next;
Q.push(dia[fuck]);
}
//dia[it.next]=tt;
}
else
{
dia[it.next].pre=it.pre;
dia[it.pre].next=it.next;
Q.push(dia[it.next]);
Q.push(dia[it.pre]);
}
}
else
{
if(it.next==cnt&&it.pre!=-1)
{
dia[it.pre].next=cnt;
Q.push(dia[it.pre]);
}
if(it.next!=cnt&&it.pre==-1)
{
dia[it.next].pre=-1;
Q.push(dia[it.next]);
}
}
}
}
return 0;
}