Codeforces Round 893 (Div. 2) E1. Rollbacks (Easy Version)

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值