Codeforces Round 893 (Div. 2) E1. Rollbacks (Easy Version)思路:单点更新+离线莫队区间查询区间不同数字个数+栈保留last_state
源代码:
#include<cstdio>
#include<cmath>
#include<algorithm>
#include <stack>
using namespace std;
const int MAXN=1000005,MAXA=1000005;
struct query{
int l,r,ti,id;
};
int N,OP,blksiz,q,m;
int a[MAXN],mod[MAXN][3];
int ans[MAXN];
query que[MAXN];
bool CaptainMo(query a,query b){
a.l/=blksiz;a.r/=blksiz;
b.l/=blksiz;b.r/=blksiz;
if(a.l==b.l)
return a.r<b.r||(a.r==b.r&&a.ti<b.ti);
return a.l<b.l;
}
int l,r,t,tans;
int cnt[MAXA];
void add(int x){
cnt[x]++;
tans+=(cnt[x]==1);
}
void del(int x){
cnt[x]--;
tans-=(cnt[x]==0);
}
void go(){
t++;
if(l<=mod[t][0]&&mod[t][0]<=r){
del(mod[t][2]);
add(mod[t][1]);
}
a[mod[t][0]]=mod[t][1];
}
void back(){
if(l<=mod[t][0]&&mod[t][0]<=r){
del(mod[t][1]);
add(mod[t][2]);
}
a[mod[t][0]]=mod[t][2];
t--;
}
struct last_state{
char c;
int x;
};
stack<last_state> st;
int main(){
int N;
scanf("%d",&N);
OP = N;
blksiz=pow(N,2.0/3.0);
char ch;
int x;
int lx,rx;
int tot = 0;
char last_ch = '*';
int last_x = 0;
for(int i = 1;i <= OP;i++){
getchar();
scanf("%c", &ch);
//cout << "tot:" << tot << endl;
switch(ch){
case '+':{
++tot;
++m;
scanf("%d", &x);
mod[m][0] = tot;
mod[m][1] = x;
//last_x = a[tot];
st.push({'+', a[tot]});
a[tot] = x;
//last_ch = '+';
break;
}
case '-':{
scanf("%d", &x);
tot -= x;
//last_ch = '-';
//last_x = x;
st.push({'-', x});
break;
}
case '!':{
struct last_state ls_temp = st.top();
st.pop();
last_ch = ls_temp.c;
last_x = ls_temp.x;
if(last_ch == '+'){
m++;
mod[m][0] = tot;
mod[m][1] = last_x;
a[tot] = last_x;
--tot;
}
else if(last_ch == '-'){
tot += last_x;
}
break;
}
case '?':{
lx = 1;
rx = tot;
//cout << lx << " " << rx << endl;
++q;
que[q] = {lx, rx, m, q};
break;
}
}
/*for(int i = 1;i <= tot;i++){
if(i-1) cout << " ";
cout << a[i];
}
cout << endl;*/
}
for(int i=1;i<=m;i++)
mod[i][2]=a[mod[i][0]],a[mod[i][0]]=mod[i][1];
for(int i=m;i>0;i--)
a[mod[i][0]]=mod[i][2];
sort(que+1,que+q+1,CaptainMo);
l=1,r=1,t=0,tans=1;
cnt[a[1]]=1;
for(int i=1;i<=q;i++){
while(t<que[i].ti)
go();
while(t>que[i].ti)
back();
while(l<que[i].l)
del(a[l]),l++;
while(l>que[i].l)
l--,add(a[l]);
while(r<que[i].r)
r++,add(a[r]);
while(r>que[i].r)
del(a[r]),r--;
ans[que[i].id]=tans;
}
for(int i=1;i<=q;i++)
printf("%d\n",ans[i]);
return 0;
}
总结:终于把这个E题过了,虽然比赛时没过,但也算差点top200呀2333记录一下赛后一小时内自主补E题,说明前面的题还是做得不够快呀2333