Educational Codeforces Round 61 (Rated for Div. 2) G(线段树,单调栈)

#include<bits/stdc++.h>
using namespace std;
int st[1000007];
int top;
int s[1000007],t[1000007];
int mx[4000007];
int sum[4000007];
int head[1000007],to[2000007],nex[2000007];
int n,k;
int a[10000077];
int dfn;
int tot;
void pushup(int rt){
    mx[rt]=max(mx[rt<<1],mx[rt<<1|1]);
}
void pushdown(int rt){
    if(sum[rt]){
        sum[rt<<1]+=sum[rt];
        sum[rt<<1|1]+=sum[rt];
        mx[rt<<1]+=sum[rt];
        mx[rt<<1|1]+=sum[rt];
        sum[rt]=0;
    }
}
void change(int rt,int l,int r,int L,int R,int x){//线段树区间更新
    if(L<=l&&r<=R){
        sum[rt]+=x;
        mx[rt]+=x;
        return ;
    }
    pushdown(rt);
    int mid=(l+r)>>1;
    if(L<=mid)
        change(rt<<1,l,mid,L,R,x);
    if(R>mid)
        change(rt<<1|1,mid+1,r,L,R,x);
    pushup(rt);
}
void add(int x,int y){//链式前向星,连边
    nex[++tot]=head[x];//上一条边
    head[x]=tot;//最后一条边
    to[tot]=y;//连向的点
}
void dfs(int x){
    s[x]=++dfn;//这个点子树深度的最小值
    for(int i=head[x];i;i=nex[i])
        dfs(to[i]);
    t[x]=dfn;//这个点子树深度的最大值
}
int main(){
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        while(top&&a[st[top]]<a[i]){//单调栈
            add(i,st[top]);//连边,前一个是后一个离得最近的比它大的数的位置
            top--;
        }
        st[++top]=i;//进入栈顶
    }
    while(top){
        add(n+1,st[top]);//顶端的数字给一个根节点将它们建成树
        top--;
    }
    dfs(n+1);//从根节点遍历
    for(int i=1;i<=k;i++)
        change(1,1,n+1,s[i],t[i],1);
    printf("%d ",mx[1]);
    for(int i=k+1;i<=n;i++){
        change(1,1,n+1,s[i],t[i],1);//当区间右端点右移时,新加入区间的这个数会对原区间中比这个数小的数的答案+1,也就是将这个数在树上的子树中所有点的答案+1(这些答案+1的所有点中虽然包括区间之前的数但显然这些数的答案不会比区间内数的答案更大,最多只会与最大值相同)
        change(1,1,n+1,s[i-k],t[i-k],-1);//同样当区间左端点右移时,就将这个数在树上的子树中所有点的答案−1来确保区间之前的数的答案不会比区间中数的答案更优
        printf("%d ",mx[1]);
    }
}

原文地址:https://www.cnblogs.com/ldudxy/p/10611902.html

时间: 2024-10-28 14:23:34

Educational Codeforces Round 61 (Rated for Div. 2) G(线段树,单调栈)的相关文章

Educational Codeforces Round 61 (Rated for Div. 2)F(区间DP,思维,枚举)

#include<bits/stdc++.h>typedef long long ll;const int inf=0x3f3f3f3f;using namespace std;char b[507];int dp[507][507];int main(){    memset(dp,0x3f,sizeof(dp));    int n;    scanf("%d",&n);    scanf("%s",b+1);    for(int i=1;

Educational Codeforces Round 41 (Rated for Div. 2) G. Partitions

G. Partitions time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output You are given a set of n elements indexed from 1 to n. The weight of i-th element is wi. The weight of some subset of a given

Educational Codeforces Round 47 (Rated for Div. 2)G. Allowed Letters 网络流

题意:给你一个字符串,和每个位置可能的字符(没有就可以放任意字符)要求一个排列使得每个位置的字符在可能的字符中,求字典序最小的那个 题解:很容易判断有没有解,建6个点表示从a-f,和源点连边,容量为原串字符出现次数,再建64个点表示给定的位置的每一个状态,和汇点连边,容量为出现次数,如果a-f某个字符在状态中出现过,再把a-f和状态连边,容量inf,但是这只能求可行解,并不是字典序最小, 我们枚举每个位置该放哪个字符(a-f),假设该位置是pos,枚举的字符是x,该位置可能字符的状态是st,现在

Educational Codeforces Round 36 (Rated for Div. 2) G. Coprime Arrays

求a_i 在 [1,k]范围内,gcd(a_1,a_2...,a_n) = 1的a的数组个数. F(x)表示gcd(a_1,a_2,...,a_n) = i的a的个数 f(x)表示gcd(a_1,a_2,...,a_n) = ki的a的个数(实际上就是i的倍数) f(x) = segma(x | d) F(d) F(x) = segma(x | d) mu(d / x) * f(d) F(1) = segma(d,1,k) mu(d) * f(d) f(d) = (k / d)^n 由于k变化时

Educational Codeforces Round 48 (Rated for Div. 2)G. Appropriate Team

题意:求满足条件的(i,j)对数:\(gcd(v,a_i)=x,lcm(v,a_j)=y\) 题解:\(x|a_i,a_j|y\),\(x|y\),考虑质因子p,假设a_i中p次数为a,x中次数为b,y为c,\(a_j\)为d;a>=b,c>=d. 假设a>b,c>d,那么由于\(gcd(v,a_i)=x\),v中p的次数为b,由于\(lcm(v,a_j)=y\),那么\(max(b,d)==c\),又c>d,所以b=c<a和x|y矛盾,所以此时ij不满足条件 其他情况

Educational Codeforces Round 53 (Rated for Div. 2)G. Yet Another LCP Problem

题意:给串s,每次询问k个数a,l个数b,问a和b作为后缀的lcp的综合 题解:和bzoj3879类似,反向sam日神仙...lcp就是fail树上的lca.把点抠出来建虚树,然后在上面dp即可.(感觉之前写的svt什么玩意) //#pragma GCC optimize(2) //#pragma GCC optimize(3) //#pragma GCC optimize(4) //#pragma GCC optimize("unroll-loops") //#pragma comm

Educational Codeforces Round 80 (Rated for Div. 2)E(树状数组,模拟,思维)

1 #define HAVE_STRUCT_TIMESPEC 2 #include<bits/stdc++.h> 3 using namespace std; 4 int mn[600007],mx[600007],a[600007],pos[600007],sum[600007]; 5 int n,m; 6 int lowbit(int x){ 7 return x&(-x); 8 } 9 void add(int x,int val){//单点更新 10 while(x<60

Educational Codeforces Round 36 (Rated for Div. 2)

Educational Codeforces Round 36 (Rated for Div. 2) F. Imbalance Value of a Tree You are given a tree T consisting of n vertices. A number is written on each vertex; the number written on vertex i is ai. Let's denote the function I(x,?y) as the differ

Educational Codeforces Round 69 (Rated for Div. 2) B - Pillars

Educational Codeforces Round 69 (Rated for Div. 2) B - Pillars There are n pillars aligned in a row and numbered from 1 to n. Initially each pillar contains exactly one disk. The i-th pillar contains a disk having radius ai. You can move these disks