[雅礼集训]program(鬼知道原题叫什么名字。。。)
程序员文章站
2022-06-03 13:22:11
...
题面:
恩。。。部分分比正解难系列。。。目前还是没写出所有询问的r=n的部分。分类讨论太麻烦了。。。
还是说正解:
恩我就是这么懒。。。感觉这一部分讲得肯定比我自己描述清楚;
不过中间有个很重要的细节,由于当一个点为0时,如果立即将其删除,可能他的g[]数组就不会被标记上;
这时候就要延时删除一下;
同时判断一个”<”或”>”是否要删时就需要跳过中间正在被延时删除的点。。。
细节看代码或者自己去实现。。。我这代码直接魔改的暴力,我自己看着都头疼。。。
代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cctype>
const int maxn=100005;
const int inf=1000000007;
int n,t;
char s[maxn],a[maxn];
struct ANSWER{
int v[10];
void clear(){
for(int i=0;i<10;i++)v[i]=0;
}
ANSWER operator -(const ANSWER &b){
ANSWER c;
c.clear();
for(int i=0;i<10;i++)c.v[i]=v[i]-b.v[i];
return c;
}
}ans[maxn*10];
void write(ANSWER a){
for(int i=0;i<10;i++)printf("%d ",a.v[i]);
printf("\n");
}
int next[maxn],front[maxn];
int f[maxn],g[maxn];
void findanslow()
{
for(int i=1;i<=n;i++)f[i]=g[i]=inf;
for(int k=1;k<=n;k++)a[k]=s[k];
for(int k=1;k<=n;k++)next[k]=k+1,front[k]=k-1;
a[0]='>';
a[n+1]='>';
front[1]=0;
next[0]=1;
next[n]=0;
bool flag=true;
ans[0].clear();
int tl=0;
for(int i=1;!(i==0&&flag);i= flag ? next[i]:front[i]){
tl++;
ans[tl]=ans[tl-1];
if(flag==true)f[i]=std::min(tl-1,f[i]);
if(isdigit(a[i])){
ans[tl].v[a[i]-'0']++;
a[i]--;
}
else if(a[i]=='>'){
flag=true;
if(!i)continue;
int pos;
for( pos=next[i];a[pos]<'0';pos=next[pos]);
if(a[pos]=='>'||a[pos]=='<')a[i]='0'-1;
}
else if(a[i]=='<'){
flag=false;
int pos;
for( pos=front[i];a[pos]<'0';pos=front[pos]);
if(a[pos]=='>'||a[pos]=='<')a[i]='0'-1;
}else a[i]--;
if(flag==false)
{
for(int k=front[i]+1;k<=i;k++)
g[i]=std::min(g[i],tl);
}
if(a[i]<'0'-1)next[front[i]]=next[i],front[next[i]]=front[i];
}
f[n+1]=tl;
}
int main()
{
freopen("program.in","r",stdin);
freopen("program.out","w",stdout);
scanf("%d%d",&n,&t);
scanf("%s",s+1);
findanslow();
ANSWER zero;
zero.clear();
for(int i=1;i<=t;i++){
int tl,tr;
scanf("%d%d",&tl,&tr);
int l=f[tl];
int r=std::min(g[tl],f[tr+1]);
if(l==inf||r==inf)write(zero);
else write(ans[r]-ans[l]);
}
return 0;
}
上一篇: 笔记——最短路径Dijkstra算法
下一篇: 每日一算法1