Codeforces Round #321 (Div. 2) E - Kefa and Watch

题目大意:给你一个由0-9组成的字符串,有m个询问,两种操作,第一种将l到r的字符全部变成c,第二种问l到r这段

字符串的循环节是不是d。

思路:首先我们要知道怎么判断字符串的循环节的长度是不是d,如果这个字符串小于等于d,那么肯定是的,否则,如果l 到 r-d

和l+d 到 r 这两段字符串则循环节的长度是d,反之不是。 然后我们就用线段树维护区间字符串哈希值就好啦。

#include<bits/stdc++.h>
#define read(x) scanf("%d",&x)
#define lread(x) scanf("%lld",&x)
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define mk make_pair
using namespace std;

typedef long long ll;
const int N=1e5+7;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int mod=1998030377;
const int base=10;

int n,m,k;
ll b[N],sum[N];

struct seg_tree
{
    struct node
    {
        ll hs;
        int l,r,lazy;
    }a[N<<2];
    void up(int l,int r,int rt)
    {
        int mid=(l+r)>>1;
        int len=r-mid;
        a[rt].hs=(a[rt<<1].hs*b[len]+a[rt<<1|1].hs)%mod;
    }
    void down(int l,int r,int rt)
    {
        if(a[rt].lazy==-1) return;
        int c=a[rt].lazy; a[rt].lazy=-1;
        a[rt<<1].lazy=a[rt<<1|1].lazy=c;
        int mid=(l+r)>>1;
        a[rt<<1].hs=c*sum[mid-l]%mod;
        a[rt<<1|1].hs=c*sum[r-mid-1]%mod;
    }
    void build(int l,int r,int rt)
    {
        a[rt].l=l; a[rt].r=r;
        a[rt].lazy=-1;
        if(l==r)
        {
            int x; scanf("%1d",&x);
            a[rt].hs=x;
            return;
        }
        int mid=(l+r)>>1;
        build(l,mid,rt<<1);
        build(mid+1,r,rt<<1|1);
        up(l,r,rt);
    }
    void updata(int L,int R,int c,int rt)
    {
        int l=a[rt].l,r=a[rt].r;
        if(l>=L && r<=R)
        {
            a[rt].lazy=c;
            a[rt].hs=c*(sum[r-l])%mod;
            return;
        }
        down(l,r,rt);
        int mid=(l+r)>>1;
        if(L<=mid) updata(L,R,c,rt<<1);
        if(R>mid) updata(L,R,c,rt<<1|1);
        up(l,r,rt);
    }
    ll query(int L,int R,int rt)
    {
        int l=a[rt].l,r=a[rt].r;
        if(l>=L && r<=R)
            return a[rt].hs;
        down(l,r,rt);
        int mid=(l+r)>>1;
        ll ans=0;
        int len=max(0,min(R,r)-mid);
        if(R>mid) ans=query(L,R,rt<<1|1);
        if(L<=mid) ans=(ans+query(L,R,rt<<1)*b[len])%mod;
        return ans;
    }
}seg;
bool check(int l,int r,int d)
{
    if(r-l+1<=d)
        return true;
    ll hs1=seg.query(l,r-d,1);
    ll hs2=seg.query(l+d,r,1);
    return hs1==hs2;
}
void init()
{
    b[0]=1; sum[0]=1;
    for(int i=1;i<N;i++)
        b[i]=b[i-1]*base%mod;
    for(int i=1;i<N;i++)
        sum[i]=(sum[i-1]+b[i])%mod;
}
int main()
{
    init();
    read(n); read(m); read(k);
    seg.build(1,n,1);
    for(int i=1;i<=m+k;i++)
    {
        int op,l,r;
        read(op);
        read(l); read(r);
        if(op==1)
        {
            int c; read(c);
            seg.updata(l,r,c,1);
        }
        else
        {
            int d; read(d);
            if(check(l,r,d))
                puts("YES");
            else
                puts("NO");
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/CJLHY/p/8453344.html

时间: 2024-10-13 22:37:44

Codeforces Round #321 (Div. 2) E - Kefa and Watch的相关文章

codeforces水题100道 第十四题 Codeforces Round #321 (Div. 2) A. Kefa and First Steps (brute force)

题目链接:http://www.codeforces.com/problemset/problem/580/A题意:求最长连续非降子序列的长度.C++代码: #include <iostream> using namespace std; const int maxn = 100100; int n, a[maxn], tmp, ans; int main() { cin >> n; for (int i = 0; i < n; i ++) cin >> a[i]

Codeforces Round #321 (Div. 2) D. Kefa and Dishes (状压dp,再A一发)

题意: 有n个菜,需要m个菜,k个规则  每个菜吃下去的满足感为 a1......an 每个规则: 吃完第u个菜后吃第v个菜满足感+c; 问:怎么吃才能幸福感最大? dp[1<<18][20]:一维表示吃了的菜(1表示吃了,0表吃没吃),第二维表示最后一个吃的菜 dp的初始化: dp[1<<i][i] = saty[i]; 状态转移:dp[i|(1 << k)][k] = max(dp[i][j] + rule[j][k] + safy[k],dp[i|(1 <&

Codeforces Round #321 (Div. 2) D Kefa and Dishes

用spfa,和dp是一样的.转移只和最后一个吃的dish和吃了哪些有关. 把松弛改成变长.因为是DAG,所以一定没环.状态最多有84934656,514ms跑过,cf机子就是快. #include<bits/stdc++.h> using namespace std; typedef pair<int,int> nd; typedef long long ll; #define fi first #define se second int n,m,a[18]; int g[18][

Codeforces Round #321 (Div. 2) C Kefa and Park

dfs一遍,维护当前连续遇到的喵的数量,然后剪枝,每个统计孩子数量判断是不是叶子结点. #include<bits/stdc++.h> using namespace std; const int maxn = 2e5+5; int a[maxn]; int head[maxn],nxt[maxn<<1],to[maxn<<1],ect; inline void addEdge(int u,int v) { to[ect] = v; nxt[ect] = head[u]

Codeforces Round #321 (Div. 2) B. Kefa and Company

排序以后O(n)枚举尾部.头部单调,维护一下就好. #include<bits/stdc++.h> using namespace std; typedef long long ll; //#define LOCAL const int maxn = 1e5+5; struct Node { int m,s; void IN(){ scanf("%d%d",&m,&s); } bool operator < (const Node&rh) co

Codeforces Round #321 (Div. 2) Kefa and Park 深搜

原题链接: 题意: 给你一棵有根树,某些节点的权值是1,其他的是0,问你从根到叶子节点的权值和不超过m的路径有多少条. 题解: 直接dfs一下就好了. 代码: #include<iostream> #include<cstring> #include<vector> #include<algorithm> #define MAX_N 100005 using namespace std; vector<int> G[MAX_N]; int n,m

Codeforces Round #321 (Div. 2) A, B, C, D, E

580A. Kefa and First Steps 题目链接: A. Kefa and First Steps 题意描述: 给出一个序列,求最长公共子序列多长? 解题思路: 水题,签到 代码: 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 7 int main () 8 { 9 in

2017-5-6-Train:Codeforces Round #321 (Div. 2)

A. Kefa and First Steps(最长不下降子串) Kefa decided to make some money doing business on the Internet for exactly n days. He knows that on the i-th day (1 ≤ i ≤ n) he makes a**i money. Kefa loves progress, that's why he wants to know the length of the maxi

CodeForces Round 321 div 2

最近做的div2,很水的一次. 1)求最长不下降子序列.听说还要dp?这里的不下降子序列必须要求连续...所以水过 #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <iostream> #include <string> #include <queue> #include <vector> #in