CSP模拟11


(抖)

A: One

约瑟夫问题
考试的时候没想出来 (wtcl)
30pts: 直接大力模拟 用vis标记人是否死过 如果死过就不报数了

60pts: STL vector可以直接碾过去
考虑为什么30pts会慢 因为vis跳的时候很多没用的操作
可以用pos链表记录一下该跳到哪个人 可以省去遍历死去人的时间

正解是推柿子 其实之前讲过了类似解法但是并没有想出来
大概是每次从0开始编号 然后柿子推一推就好了 主要思想是求出当前活着的人在上一轮的编号 然后递推就完了

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

int main(){
    freopen("one.in","r",stdin);
    freopen("one.out","w",stdout);
    int T;scanf("%d",&T);
    while(T--) {
        int n;scanf("%d",&n);
        int nw = 0;
        for(int i = 2;i <= n;++i) nw = (nw - i + 1 + n) % i;
        cout << nw + 1 << endl;
    }
    return 0;
}

B:哪一天她能重回我身边

纯模拟
记录几种情况随便打打


#include<bits/stdc++.h>
using namespace std;
const int maxn = 1000;
const int now = maxn;
char s[maxn];
int cnt[maxn << 1][maxn << 1];
int k;

int main(){
    freopen("block.in","r",stdin);
    freopen("block.out","w",stdout);
    int T;scanf("%d",&T);
    while(T--) {
        memset(cnt,0,sizeof(cnt));
        scanf("%d",&k); scanf("%s",s + 1);
        int len = strlen(s + 1);
        if(k == 1) {
            int x = 0,y = 0;
            cnt[x + now][y + now]++;
            int Max = 1;
            for(int i = 1;i <= len;++i) {
                if(s[i] == 'N') y++;
                if(s[i] == 'S') y--;
                if(s[i] == 'E') x++;
                if(s[i] == 'W') x--;
                ++cnt[x + now][y + now];
                if(cnt[x + now][y + now] > Max) Max = cnt[x + now][y + now];
            }
            printf("%d
%d
%d
",x,y,Max);
        }
        else {
            int cur = 1;
            int x = 0,y = 0;
            cnt[x + now][y + now]++;
            int Max = 1;
            for(int i = 1;i <= len;++i) {
                if(cur == 1) {
                    if(s[i] == 'N') {
                        y++;
                        for(int j = y;j <= y + k - 1;++j) {
                            cnt[x + now][j + now]++;
                            if(cnt[x + now][j + now] > Max) Max = cnt[x + now][j + now];
                        }
                        cur = 2;
                    }
                    if(s[i] == 'S') {
                        y -= k;
                        for(int j = y;j <= y + k - 1;++j) {
                            cnt[x + now][j + now]++;
                            if(cnt[x + now][j + now] > Max) Max = cnt[x + now][j + now];
                        }
                        cur = 2;
                    }
                    if(s[i] == 'E') {
                        x++;
                        for(int j = x;j <= x + k - 1;++j) {
                            cnt[j + now][y + now]++;
                            if(cnt[j + now][y + now] > Max) Max = cnt[j + now][y + now];
                        }
                        cur = 3;
                    }
                    if(s[i] == 'W') {
                        x -= k;
                        for(int j = x;j <= x + k - 1;++j) {
                            cnt[j + now][y + now]++;
                            if(cnt[j + now][y + now] > Max) Max = cnt[j + now][y + now];
                        }
                        cur = 3;
                    }
                    //cout << cur << endl;
                    continue;
                }
                if(cur == 2) {
                    if(s[i] == 'N') {
                        y += k;
                        cnt[x + now][y + now]++;
                        if(cnt[x + now][y + now] > Max) Max = cnt[x + now][y + now];
                        cur = 1;
                    }
                    if(s[i] == 'S') {
                        y--;
                        cnt[x + now][y + now]++;
                        if(cnt[x + now][y + now] > Max) Max = cnt[x + now][y + now];
                        cur = 1;
                    }
                    if(s[i] == 'E') {
                        x++;
                        for(int j = y;j <= y + k - 1;++j) {
                            cnt[x + now][j + now]++;
                            if(cnt[x + now][j + now] > Max) Max = cnt[x + now][j + now];
                        }
                        cur = 2;
                    }
                    if(s[i] == 'W') {
                        x--;
                        for(int j = y;j <= y + k - 1;++j) {
                            cnt[x + now][j + now]++;
                            if(cnt[x + now][j + now] > Max) Max = cnt[x + now][j + now];
                        }
                        cur = 2;
                    }
                    //cout << cur << endl;
                    continue;
                }
                if(cur == 3) {
                    if(s[i] == 'N') {
                        y++;
                        for(int j = x;j <= x + k - 1;++j) {
                            cnt[j + now][y + now]++;
                            if(cnt[j + now][y + now] > Max) Max = cnt[j + now][y + now];
                        }
                        cur = 3;
                    }
                    if(s[i] == 'S') {
                        y--;
                        for(int j = x;j <= x + k - 1;++j) {
                            cnt[j + now][y + now]++;
                            if(cnt[j + now][y + now] > Max) Max = cnt[j + now][y + now];
                        }
                        cur = 3;
                    }
                    if(s[i] == 'E') {
                        x += k;
                        cnt[x + now][y + now]++;
                        if(cnt[x + now][y + now] > Max) Max = cnt[x + now][y + now];
                        cur = 1;
                    }
                    if(s[i] == 'W') {
                        x--;
                        cnt[x + now][y + now]++;
                        if(cnt[x + now][y + now] > Max) Max = cnt[x + now][y + now];
                        cur = 1;
                    }
                    //cout << cur << endl;
                    continue;
                }
            }
            if(cur == 1) {
                printf("%d
%d
%d
",x,y,Max);
            }
            if(cur == 2) {
                for(int i = 1;i <= k;++i) printf("%d ",x);
                printf("
");
                for(int i = y;i <= y + k - 1;++i) printf("%d ",i);
                printf("
%d
",Max);
            }
            if(cur == 3) {
                for(int i = x;i <= x + k - 1;++i) printf("%d ",i);
                printf("
");
                for(int i = 1;i <= k;++i) printf("%d ",y);
                printf("
%d
",Max);
            }
        }
    }
    return 0;
}

C: 数字

然而似乎并不会
害怕.jpg

D: 甜圈

两种解题方法
正解 : 对操作哈希 然后求有多少个叶子节点的值等于我们要求的值就好了 对于每次区间一次操作 就是一次区间乘带一次区间加 最后把所有lazy 都pushdown下去统计答案
另一种思路: 可以保存当前区间进行过哪些次操作 l 和 r表示时间最早和最晚的操作是什么 对于一个区间 如果不合法就让l 和 r都等于-1 如果并没有进行过任何操作就是0
对于0的状态显然一定合法 然后如果对于区间进行了一次修改 那就保留一个lazy 标记 然后如果可以和子区间中的r进行合并就让它合并 最后大力pushdown 然后统计答案



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

typedef unsigned long long ull;

const int maxn = 2e5 + 10;
const ull base = 233;
int ans = 0;

ull t[maxn << 2];
ull add[maxn << 2]; //加法标记
ull mul[maxn << 2];

void pushdown(int rt,int l,int r){
	int mid = l + r >> 1;
	t[rt << 1] = t[rt << 1] * mul[rt] + add[rt] * (mid - l + 1);
	t[rt << 1 | 1] = t[rt << 1 | 1] * mul[rt] + add[rt] * (r - mid);
	add[rt << 1] = add[rt << 1] * mul[rt] + add[rt];
	add[rt << 1 | 1] = add[rt << 1 | 1] * mul[rt] + add[rt];
	mul[rt << 1] *= mul[rt];
	mul[rt << 1 | 1] *= mul[rt];
	mul[rt] = 1; add[rt] = 0;
}

void modify(int rt,int l,int r,int L,int R,int k){
	if(L <= l && R >= r) return t[rt] += k * (r - l + 1),add[rt] += k,void();
	int mid = l + r >> 1;
	pushdown(rt,l,r);
	if(L <= mid) modify(rt << 1,l,mid,L,R,k);
	if(R > mid) modify(rt << 1 | 1,mid + 1,r,L,R,k);
	t[rt] = t[rt << 1] + t[rt << 1 | 1];
}

void mult(int rt,int l,int r,int L,int R,int k){
	if(L <= l && R >= r) return add[rt] *= k,mul[rt] *= k,t[rt] *= k,void();
	int mid = l + r >> 1;
	pushdown(rt,l,r);
	if(L <= mid) mult(rt << 1,l,mid,L,R,k);
	if(R > mid) mult(rt << 1 | 1,mid + 1,r,L,R,k);
	t[rt] = t[rt << 1] + t[rt << 1 | 1];
}

int ask(int rt,int l,int r,int L,int R){
	if(L <= l && R >= r) return t[rt];
	int mid = l + r >> 1;
	pushdown(rt,l,r);
	if(R <= mid) return ask(rt << 1,l,mid,L,R);
	if(L > mid) return ask(rt << 1 | 1,mid + 1,r,L,R);
	return ask(rt << 1,l,mid,L,R) + ask(rt << 1 | 1,mid + 1,r,L,R);
}

int main(){
	freopen("deco.in","r",stdin);
	freopen("deco.out","w",stdout);
	int n,K,T;scanf("%d%d%d",&n,&K,&T);
	memset(mul,1,sizeof(mul));
	for(int i = 1;i <= T;++i) {
		int l,r,x;scanf("%d%d%d",&l,&r,&x);
		mult(1,1,n,l,r,base);
		modify(1,1,n,l,r,x);
	}
	int T_T = 0;
	for(int i = 1;i <= K;++i) T_T = T_T * base + i;
	for(int i = 1;i <= n;++i) if(ask(1,1,n,i,i) == T_T) ans++;
	cout << ans << endl;
	return 0;
}

如初见 与初见
原文地址:https://www.cnblogs.com/HISKrrr/p/13782858.html