2017 暑假艾教集訓 day6


CF 240F
做法:二維線段樹,分別記錄一個區間的小寫字母個數,每次從小到大給兩邊分配(字典序最小)(區間更改)!


#include <bits/stdc++.h>
#define lson rt<<1,begin,mid
#define rson rt<<1|1,mid+1,end
using namespace std;
const int maxn= 100100;
char str[maxn];
int tree[maxn<<3][28];
int lazy[maxn<<3];
int book[28];
int n,m;

void cls(int rt)
{
    lazy[rt]=-1;
    for(int i=0;i<26;++i) tree[rt][i]=0;
}
void pushup(int rt)
{
    for(int i=0;i<26;++i) tree[rt][i] = tree[rt<<1][i] + tree[rt<<1|1][i];
}
void pushdown(int rt,int begin,int end)
{
    if(lazy[rt]!=-1)
    {
        int mid=(begin + end)/2;
        int id=lazy[rt];
        cls(rt<<1); cls(rt<<1|1);

        tree[rt<<1][id]= (mid-begin+1);
        tree[rt<<1|1][id] = (end-mid);
        lazy[rt<<1]=lazy[rt<<1|1] =lazy[rt];
        lazy[rt]=-1;
    }
}
void build(int rt,int begin,int end)
{
    cls(rt);
    if(begin==end)
    {
        int id=str[begin] - 'a';
        tree[rt][id]++;
        lazy[rt]=id;
        return;
    }
    int mid=(begin + end)>>1;
    build(rson);
    build(lson);
    pushup(rt);
}
void updata(int rt,int begin,int end,int l,int r,int id)
{
    if(begin>=l && r>=end)
    {
        cls(rt);
        tree[rt][id] = (end-begin+1);
        lazy[rt]=id;
        return ;
    }
    pushdown(rt,begin,end);
    int mid=(begin + end)>>1;
    if(mid>=l) updata(lson,l,r,id);
    if(r>mid) updata(rson,l,r,id);
    pushup(rt);
}
void query(int rt,int begin,int end,int l,int r)
{
   if(begin >=l && r>=end)
   {
       for(int i=0;i<26;++i) book[i]+=tree[rt][i];
       return ;
   }
   pushdown(rt,begin,end);
   int mid=(begin + end)>>1;
   if(mid>=l) query(lson,l,r);
   if(r>mid) query(rson,l,r);
   pushup(rt);
}
void work(int l,int r)
{
    memset(book,0,sizeof(book));
    query(1,1,n,l,r);
    int flag=0;
    for(int i=0;i<26;++i)
    {
        if(book[i] % 2) flag++;
        if(flag > 1) return;
    }

    int st=l,en=r;
    int mid=l+(r-l+1)/2;
    for(int i=0;i<26;++i)
    {
        if(book[i]==0) continue;

        int temp= book[i]/2;
        if(temp)
        {
            updata(1,1,n,st,st+temp-1,i);
            updata(1,1,n,en-temp+1,en,i);

            st= st+temp;
            en= en-temp;
        }
        if(book[i]%2) updata(1,1,n,mid,mid,i);
    }
}
int main()
{
    freopen("input.txt","r",stdin);
	freopen("output.txt","w",stdout);
    scanf("%d%d",&n,&m);
    scanf("%s",str+1);
    build(1,1,n);
    int a,b;
    while(m--)
    {
        scanf("%d%d",&a,&b);
        work(a,b);
    }
    for(int i=1;i<=n;++i)
    {
        memset(book,0,sizeof(book));
        query(1,1,n,i,i);
        for(int j=0;j<26;++j)
        {
            if(book[j])
            {
                putchar(j+'a');
                break;
            }
        }
    }
    putchar(10);
    return 0;
}


Cf 343D
做法:DFS序加線段樹 ,這裏要注意的是二操作,因爲要區間修改其祖先很難實現。這時候我們可以這麼想,先對修改點單點修改,然後在詢問時,取DFS序子節點的min值即可。
注意:這裏有一個wa點,如果當前點爲0的話,在進行操作1的時候需要把這個0扔給它的祖先,避免在更改1後出現漏更改的情況!!!

#include <bits/stdc++.h>
#define lson rt<<1,begin,mid
#define rson rt<<1|1,mid+1,end
using namespace std;
const int maxn=500005;
int tree[maxn<<3];
int lazy[maxn<<3];
//如果其兒子有一點爲0的話,那麼本身也一定是0
void pushup(int rt)
{
    tree[rt] = tree[rt<<1] && tree[rt<<1|1];
}
void pushdown(int rt)
{
    if(lazy[rt]!=-1)
    {
        tree[rt<<1] = tree[rt<<1|1] =lazy[rt];
        lazy[rt<<1|1] =lazy[rt<<1] =lazy[rt];
        lazy[rt] = -1;
    }
}
void updata(int rt,int begin,int end,int l,int r ,int x)
{
    if(begin >= l && r>=end)
    {
        tree[rt] = x;
        lazy[rt] = x;
        return ;
    }
    pushdown(rt);
    int mid=(begin + end)>>1;
    if(mid >= l) updata(lson,l,r,x);
    if(r>mid) updata(rson,l,r,x);
    pushup(rt);
}
//單點更新
void updata2(int rt,int begin,int end,int pos)
{
    if(begin==end)
    {
        tree[rt] = 0;
        return ;
    }
    pushdown(rt);
    int mid=(begin +end)>>1;
    if(mid >=pos) updata2(lson,pos);
    else updata2(rson,pos);
    pushup(rt);
}
//兒子中如果有0的話,那麼其點一定是0
int  query(int rt,int begin, int end,int l,int r)
{
    if(begin >=l && r>= end)
    {
        return tree[rt];
    }
    pushdown(rt);
    int mid=(begin +end )>>1;
    int a=3;
    if(mid >=l) a= min( query(lson ,l,r),a);
    if(r>mid) a=min(a, query(rson,l,r));
    return a;
}

struct node
{
    int to,next;
}edge[maxn<<1];
int head[maxn];
int cnt=0;

void add(int u,int v)
{
    edge[cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt++;
}

int fis[maxn];
int two[maxn];
int tot;
int fa[maxn];
void dfs(int u , int pre)
{
    fis[u] = ++tot;
    fa[u]=pre;
    for(int i=head[u] ; i!=-1; i=edge[i].next )
    {
        int v=edge[i].to;
        if(fis[v]==-1) dfs(v,u);
    }
    two[u]=tot;
}
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        memset(head,-1,sizeof(head)); cnt=0;
        for(int i=1;i<n;++i)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            add(a,b); add(b,a);
        }

        memset(fis,-1,sizeof(fis)); tot=0;
        dfs(1,-1);

        memset(tree,0,sizeof(tree));
        memset(lazy,-1,sizeof(lazy));

        int m;
        scanf("%d",&m);
        while(m--)
        {
           int op,v;
           scanf("%d%d",&op,&v);
           if(op==1)
           {
               if(!query(1,1,tot,fis[v],two[v]) && fa[v]!=-1) updata2(1,1,tot,fis[fa[v]]);
               // 如果其爲0的話,那說明它的祖先也一定爲0
               updata(1,1,tot,fis[v],two[v],1);
           }
           else if(op==2)
           {
              updata2(1,1,tot,fis[v]);
              //單點更新
           }
           else if(op==3)
           {
               printf("%d\n",query(1,1,tot,fis[v],two[v]));
           }
        }

    }
    return 0;
}



POJ  2104
做法:主席樹模板(默默收藏一發)


#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn= (100005<<2);
int tree[maxn*30],lson[maxn*30],rson[maxn*30];
int root[maxn],tot;
int a[maxn],myhash[maxn];

void build(int &rt,int begin ,int end)
{
    rt = ++tot;
    tree[rt]=0;
    if(begin == end) return;
    int mid=(begin+end)>>1;
    build(lson[rt],begin,mid);
    build(rson[rt],mid+1,end);
}
void updata(int pre,int &rt,int begin, int end,int pos)
{
    rt =  ++tot;
    tree[rt] = tree[pre] +1;
    lson[rt] = lson[pre];
    rson[rt] = rson[pre];
    if(begin == end) return;
    int mid=(begin + end) >>1;
    if(mid >= pos) updata(lson[pre],lson[rt],begin,mid,pos);
    else  updata(rson[pre],rson[rt],mid+1,end,pos);
}
int query(int pre,int rt,int begin ,int end,int k)
{
    if(begin == end)
    {
        return begin;
    }
    int have = (tree[lson[rt]]-tree[lson[pre]]);
    int mid =  (begin+end)>>1;
    if(have>=k) return query(lson[pre],lson[rt],begin,mid,k);
    else return  query(rson[pre],rson[rt],mid+1,end,k-have);
}
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(int i=1;i<=n;++i)
        {
            scanf("%d",&a[i]);
            myhash[i]=a[i];
        }
        sort(myhash+1,myhash+n+1);
        int cnt = unique(myhash+1,myhash+n+1) - myhash -1;
        build(root[0], 1, cnt);
        for(int i=1;i<=n;++i)
        {
            int temp = lower_bound(myhash+1,myhash+cnt+1,a[i]) - myhash;
            updata(root[i-1],root[i],1,cnt,temp);
        }
        while(m--)
        {
            int l,r,k;
            scanf("%d%d%d",&l,&r,&k);
            printf("%d\n",myhash[query(root[l-1],root[r],1,cnt,k)]);
        }
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章