列表

详情


NC20710. Stringsobits

描述

给定一个长n的01串s,有4种操作:
1. 区间赋值为0;
2. 区间赋值为1;
3. 撤销第i次操作(保证第i次操作的种类为区间赋值)(撤销不影响前面或后面的操作);
4. 查询区间中1的个数。
现在有m次操作,你需要对每次询问(操作4)输出答案。

例如:串s为:0000
1. 区间[3,4]赋值为1:0011
2. 区间[2,3]赋值为1:0111
3. 撤销第1次操作,串s变成:0110

输入描述

第一行两个整数n,m,分别表示s的长度及操作总数。
第二行一个长为n的串s。
接下来m行,第一个数opt为操作种类(1≤opt≤4)。
若opt=1,接下来两个整数l,r,表示将s[l..r]赋值为0。
若opt=2,接下来两个整数l,r,表示将s[l..r]赋值为1。
若opt=3,接下来一个整数k,表示撤销第k次操作optk
若opt=4,接下来两个整数l,r,表示询问s[l..r]中1的个数。
保证1≤li≤ri≤n;
保证opti=3时,optk=1或2(即撤销的操作种类为操作一或操作二)。
一个操作不会被撤销多次。

输出描述

对于每次操作4,输出一行一个整数,表示询问区间s[l..r]中1的个数。

示例1

输入:

4 6
0000
2 3 4
4 2 3
2 2 3
4 2 3
3 1
4 2 3

输出:

1
2
2

说明:

输入样例即题目描述中的例子。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C(clang 3.9) 解法, 执行用时: 496ms, 内存消耗: 196696K, 提交时间: 2018-12-15 19:10:09

#include<stdio.h>
int main (void)
{
    int n,m;
    scanf("%d%d",&n,&m);
    int i,j;
    char cs[n];
    char s[n];
    scanf("%s",cs);
    for(i=0;i<n;i++)
        if(cs[i]=='0')
            s[i]=0;
        else
            s[i]=1;
    int op[m+1][3];
    for(i=1;i<=m;i++){
        scanf("%d",&op[i][0]);
        if(op[i][0]==3)
            scanf("%d",&op[i][1]);
        else{
            scanf("%d%d",&op[i][1],&op[i][2]);
            op[i][1]--;
            op[i][2]--;
        }
    }
    
    char val[m+1][n];
    int k;
    int count;
    for(i=0;i<m+1;i++)
        for(j=0;j<n;j++)
            val[i][j]=2;
    for(i=0;i<n;i++)
        val[0][i]=s[i];
    for(i=1;i<=m;i++){
        switch(op[i][0]){
            case 1:
                for(j=op[i][1];j<=op[i][2];j++)
                    val[i][j]=0;
                break;
            case 2:
                for(j=op[i][1];j<=op[i][2];j++)
                    val[i][j]=1;
                break;
            case 3:
                for(j=0;j<n;j++)
                    val[op[i][1]][j]=2;
                break;
            case 4:
                count =0;
                for(j=op[i][1];j<=op[i][2];j++){
                    k=i;
                    while(val[k][j]==2)
                        k--;
                    if(val[k][j])
                        count++;
                }
                printf("%d\n",count);
                break;
        }
    }
    return 0;
}

C++14(g++5.4) 解法, 执行用时: 2102ms, 内存消耗: 972K, 提交时间: 2020-08-06 14:49:25

#include<bits/stdc++.h>
using namespace std;

int i,j,n,m,l[20005],r[20005],op[20005],ans[20005];
char R[10005];
vector<pair<bool,int>>T;
int main()
{
	scanf("%d%d%s",&n,&m,R+1);
    for(i=0;i<m;i++)
	{
		scanf("%d%d",&op[i],&l[i]);
		if(op[i]!=3)scanf("%d",&r[i]);
	}
	for(i=1;i<=n;i++)
	{
		bool V[20005]={0};
		T.clear();
		for(j=0;j<m;j++)
		{
			if(op[j]!=3&&(l[j]>i||r[j]<i))continue;
			if(op[j]==1)T.push_back({0,j});
			if(op[j]==2)T.push_back({1,j});
			if(op[j]==3)V[l[j]-1]=1;
			while(T.size()&&V[T[T.size()-1].second])T.pop_back();
			if(op[j]==4)
			{
				if(T.size())ans[j]+=T[T.size()-1].first;
				else ans[j]+=R[i]-'0';
			}
		}
	}
	for(i=0;i<m;i++)if(op[i]==4)printf("%d\n",ans[i]);
    return 0;
}

C++(clang++11) 解法, 执行用时: 2204ms, 内存消耗: 243088K, 提交时间: 2021-03-07 19:58:02

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e4+5;
int n,m,f[N];
bool del[N];
char s[N];
stack<short>q[10001];
int main()
{
	scanf("%d%d",&n,&m);
	scanf("%s",s+1);
	for(int cas=1;cas<=m;cas++)
	{
		int opt;scanf("%d",&opt);
		if(opt==3)
		{
			int k;scanf("%d",&k);
			del[k]=true; 
		}
		else
		{
			int l,r;scanf("%d%d",&l,&r);
			if(opt<=2)
			{
				if(opt==1) f[cas]=0;
				else f[cas]=1;
				for(int i=l;i<=r;i++)
					q[i].push(cas);
			}
			else
			{
				int ans=0;
				for(int i=l;i<=r;i++)
				{
					while(q[i].size()&&del[q[i].top()]) q[i].pop();
					if(q[i].size()==0) ans+=s[i]-'0';
					else ans+=f[q[i].top()];
				}
				printf("%d\n",ans);
			}
		}
	}
}

上一题