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;
}