2021-06-09 线段树,莫队,树状数组练习

牛客题 - 统计颜色

1.题意:
2.题解:
3.ac代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
ll a[N];
struct Node{
    ll l,r;
    ll sum,add;
}tr[N<<2];
void pushdown(ll u){
    if(tr[u].add){
        tr[u<<1].sum|=tr[u].add;
        tr[u<<1|1].sum|=tr[u].add;
        tr[u<<1].add|=tr[u].add;
        tr[u<<1|1].add|=tr[u].add;
        tr[u].add=0;
    }
}
void pushup(Node &u,Node &l,Node &r){
    u.sum=l.sum|r.sum;
}
void pushup(ll u){
    pushup(tr[u],tr[u<<1],tr[u<<1|1]);
}
void build(ll u,ll l,ll r){
    if(l==r){
        tr[u]={l,r};
    }else{
        tr[u]={l,r};
        int mid=(l+r)>>1;
        build(u<<1,l,mid);build(u<<1|1,mid+1,r);
        pushup(u);
    }
}
void change(ll u,ll l,ll r,ll x){
    if(l<=tr[u].l&&tr[u].r<=r){
        tr[u].sum|=x;
        tr[u].add|=x;
        return;
    }else{
        //cout<<"u:"<<u<<"--l:"<<tr[u].l<<"--r:"<<tr[u].r<<"--sum:"<<tr[u].sum<<endl;
        ll mid=(tr[u].l+tr[u].r)>>1;
        pushdown(u);
        if(l<=mid) change(u<<1,l,r,x);
        if(r>mid) change(u<<1|1,l,r,x);
        pushup(u);
    }
    
}
Node query(ll u,ll l,ll r){
    if(l<=tr[u].l&&tr[u].r<=r){
        return tr[u];
    }
    ll mid=(tr[u].l+tr[u].r)>>1;
    pushdown(u);
    if(r<=mid) return query(u<<1,l,r);
    if(l>=mid) return query(u<<1|1,l,r);
    else{
        Node node;
         auto lson=query(u<<1,l,r);
         auto rson=query(u<<1|1,l,r);
        pushup(node,lson,rson);
        return node;
    }
    
    
}
int main(){
    ll n,m;
    while(cin>>n>>m){
        build(1,1,n);
    int op,l,r;
    ll x;
    for(int i=1;i<=m;i++){
        cin>>op>>l>>r;
        if(op==1){
            cin>>x;
            change(1,l,r,(ll)1<<x);
            
        }else{
            
            auto node=query(1,l,r);
             
            ll sum=node.sum;
            ll ans=0;
           while(sum){
                if(sum&1) ans++;
                sum>>=1;
            }
            cout<<ans<<endl;
        }
        }
        
    }
    
    
}

HDU - Cow Sorting (树状数组)

1.题意:
2.题解:
3.ac代码:
#include<bits/stdc++.h>
#include<string>
using namespace std;
const int N=1e5+10;
typedef long long ll;
const int big=1e5;
ll tr[N];
ll cnt[N];
ll a[N];
int n,m;
int tot;
//map<ll,int> m;
int lowbit(int x){
	return x&(-x);
} 
void add1(int l,int x){
	for(int i=l;i<=big;i+=lowbit(i)){
		tr[i]+=x;
	}
}
void add2(int l,int x){
	for(int i=l;i<=big;i+=lowbit(i)){
		cnt[i]+=x;
	}
}
ll sum1(int l){
	ll res=0;
	for(int i=l;i;i-=lowbit(i)){
		res+=tr[i];
	}
	return res;
}
ll sum2(int l){
	ll res=0;
	for(int i=l;i;i-=lowbit(i)){
		res+=cnt[i];
	}
	return res;	
}
int main(){
	int t;
	while(cin>>n){
		ll res=0;
		ll a;
		memset(cnt,0,sizeof cnt);
		memset(tr,0,sizeof tr);
		for(int i=1;i<=n;i++){
			cin>>a;
			ll ans1=sum1(big)-sum1(a);
			ll ans2=sum2(big)-sum2(a);
			res+=ans1+ans2*a;
			add2(a,1);
			add1(a,a);
		}
		cout<<res<<endl;
	}



}

HDU-Turing Tree

1.题意:
2.题解:
3.ac代码:
#include<bits/stdc++.h>
#include<string>
using namespace std;
const int N=1e5+10;
typedef long long ll;
const int big=1e5;
ll a[N];
map<ll,ll> mp;
ll sq;
struct Q{
	ll l,r,id;
	bool operator<(const Q &w)const{
		if(l/sq!=w.l/sq) return l<w.l;
		if(l/sq&1) return r<w.r;
		return r>w.r;
	}
}q[N];
ll n;
ll ans[N];
ll b[N];
ll res;
ll cnt[N];
void del(int l){
	if(cnt[b[l]]==1){
		res-=a[l];
	}
	
		cnt[b[l]]--;//!!!!万万没想到,die在这,de了一天,竟然错在这,,,!!!我一开始判断>0时才能减
	

	
}
void add(int l){
	if(cnt[b[l]]==0){
	//	cout<<"--b[a[l]:"<<b[a[l]]<<endl;
		res+=a[l];
	}
	
	cnt[b[l]]++;
	
}
int main(){
	int t;
	ll x;
	cin>>t;
	while(t--){
		mp.clear();
		cin>>n;
		res=0;
		memset(ans,0,sizeof ans);
		memset(q,0,sizeof q);
		memset(a,0,sizeof a);
		memset(b,0,sizeof b);
		memset(cnt,0,sizeof cnt);
		ll tot=0;
	
		sq=sqrt(n);
		for(int i=1;i<=n;i++){
			cin>>a[i];
			if(mp.count(a[i])==0) mp[a[i]]=++tot;
			b[i]=mp[a[i]];
		}
	
		int m;
		cin>>m;
		//int l,r;
		for(int i=1;i<=m;i++){
			cin>>q[i].l>>q[i].r;
			q[i].id=i;
		}
		sort(q+1,q+1+m);
		ll l=1,r=0;
		for(int i=1;i<=m;i++){
			while(l<q[i].l){
				del(l++);
			}
			while(l>q[i].l){
				add(--l);
			}
			while(r<q[i].r){
				add(++r);
			}
			while(r>q[i].r){
				del(r--);
			}
			ans[q[i].id]=res;
		}
		for(int i=1;i<=m;i++){
			cout<<ans[i]<<endl;
		}
	}
}

求和(DFS序+线段树/树状数组)

1.题意:
2.题解:
3.ac代码:

线段树

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+10;
int tim=0;
int h[N],e[N<<1],ne[N<<1],idx;
int w[N];
int st[N],ed[N];
int id[N];
void add(int a,int b){
	e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs(int u,int f){
	st[u]=++tim;
	id[tim]=u;
	for(int i=h[u];i!=-1;i=ne[i]){
		int j=e[i];
        if(j==f) continue;
		dfs(j,u);
	}
	ed[u]=tim;
}
struct Node{
	int l,r,val,mark;
}tr[N<<2];
// void pushdown(int u){
// 	if(tr[u].mark){
// 		int t=tr[u].mark;
// 		tr[u<<1].val+=t;
// 		tr[u<<1|1].val+=t;
// 		tr[u<<1].mark=t;
// 		tr[u<<1|1].mark=t;
// 		tr[u].mark=0;
// 	}
// }
void pushup(Node &u,Node &l,Node &r){
    u.val=l.val+r.val;
}
void pushup(int u){
    pushup(tr[u],tr[u<<1],tr[u<<1|1]);
}
void build(int u,int l,int r){
    if(l==r){
        tr[u]={l,r,w[id[l]]};
        return ;
    }
   // printf("%d,%d,%d\n",u,l,r);
    int mid=l+r>>1;
    tr[u].l=l;tr[u].r=r;
    build(u<<1,l,mid);
    build(u<<1|1,mid+1,r);
    pushup(u);
}
void change(int u,int idx,ll x){
    
    if(tr[u].l==idx&&tr[u].r==idx){
        tr[u].val+=x;
        
    }else{
        int mid=tr[u].l+tr[u].r>>1;
       // pushdown(u);
        if(idx<=mid) change(u<<1,idx,x);
        else  change(u<<1|1,idx,x);
        pushup(u);
    }


}

int query(int u,int l,int r){
	if(l>r) return 0;
    if(l<=tr[u].l&&tr[u].r<=r){
        return tr[u].val;
    }
    int mid=tr[u].l+tr[u].r>>1;
   // pushdown(u);
    int res=0;
    if(l<=mid) res=query(u<<1,l,r);
    if(r>mid) res+=query(u<<1|1,l,r);
    return res;
}
int main(){
	int n,m,k;
	cin>>n>>m>>k;
	memset(h,-1,sizeof h);
	memset(ne,-1,sizeof ne);
	for(int i=1;i<=n;i++){
		scanf("%d",&w[i]);
	}
	for(int i=1;i<=n-1;i++){
		int a,b;
		scanf("%d%d",&a,&b);
       // cout<<"a:"<<a<<"  b:"<<b<<endl;
		add(a,b),add(b,a);
	}
    
	int op,a,x;
	dfs(k,0);
  
  
	build(1,1,n);
	for(int i=1;i<=m;i++){
		scanf("%d%d",&op,&a);
		if(op==1){
			scanf("%d",&x);
			change(1,st[a],x);
		}else{
			int l=st[a],r=ed[a];
			int res=query(1,l,r);
			printf("%d\n",res);
		}
	}
}	

树状数组:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+10;
int tim=0;
int h[N],e[N<<1],ne[N<<1],idx;
int w[N];
int st[N],ed[N];
int id[N];
int n;
void add(int a,int b){
	e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs(int u,int f){
	st[u]=++tim;
	id[tim]=u;
	for(int i=h[u];i!=-1;i=ne[i]){
		int j=e[i];
        if(j==f) continue;
		dfs(j,u);
	}
	ed[u]=tim;
}
int tr[N];
int lowbit(int x){
    return x&(-x);
}
void add1(int l,int x){
    for(int i=l;i<=n;i+=lowbit(i)){
        tr[i]+=x;
    }
}
int sum(int l){
    int res=0;
    for(int i=l;i;i-=lowbit(i)){
        res+=tr[i];
    }
    return res;
}
int main(){
    int m,k;
    scanf("%d%d%d",&n,&m,&k);
    memset(ne,-1,sizeof ne);
    memset(h,-1,sizeof h);
    for(int i=1;i<=n;i++) cin>>w[i];
    for(int i=1;i<=n-1;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        add(a,b);add(b,a);
    }
    dfs(k,0);
    int op,a,x;
    for(int i=1;i<=n;i++){
        add1(st[i],w[i]);
    }
    for(int i=1;i<=m;i++){
        scanf("%d%d",&op,&a);
        if(op==1){
            scanf("%d",&x);
            add1(st[a],x);
        }else{
            int res=sum(ed[a])-sum(st[a]-1);
            printf("%d\n",res);
        }
    }
}

HDU-Assign the task(DFS序+线段树)

1.题意:
2.题解:
3.ac代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e4+10;
int tim=0;
int h[N],e[N<<1],ne[N<<1],idx;
ll w[N];
int st[N],ed[N];
int id[N];
int n;
int du[N];
void add(int a,int b){
	e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs(int u,int f){
	st[u]=++tim;
	id[tim]=u;
	for(int i=h[u];i!=-1;i=ne[i]){
		int j=e[i];
        if(j==f) continue;
		dfs(j,u);
	}
	ed[u]=tim;
}
struct Node{
	int l,r;
	ll val,mark;
}tr[N<<2];
 void pushdown(int u){
 	if(tr[u].mark!=-1){
 		int t=tr[u].mark;
 		tr[u<<1].val=t;
 		tr[u<<1|1].val=t;
 		tr[u<<1].mark=t;
 		tr[u<<1|1].mark=t;
 		tr[u].mark=-1;
 	}
 }
void pushup(Node &u,Node &l,Node &r){
    u.val=l.val+r.val;
}
void pushup(int u){
    pushup(tr[u],tr[u<<1],tr[u<<1|1]);
}
void build(int u,int l,int r){
    if(l==r){
        tr[u]={l,r,-1,-1};
        return ;
    }
   // printf("%d,%d,%d\n",u,l,r);
    int mid=l+r>>1;
    tr[u].l=l;tr[u].r=r;
    tr[u].val=tr[u].mark=-1;
    build(u<<1,l,mid);
    build(u<<1|1,mid+1,r);
    tr[u<<1].val=tr[u<<1|1].val=tr[u<<1].mark=tr[u<<1|1].mark=-1;
    //pushup(u);
}
void change(int u,int l,int r,ll x){

    if(l<=tr[u].l&&tr[u].r<=r){
    	tr[u].val=x;
    	tr[u].mark=x;
    	return ;
	}
	int mid=(tr[u].l+tr[u].r)>>1;
	pushdown(u);
	if(l<=mid) change(u<<1,l,r,x);
	if(r>mid) change(u<<1|1,l,r,x);


}

int query(int u,int idx){

    //cout<<"u: "<<u<<" l r:"<<l<<" "<<r<<"  var:"<<tr[u].val<<" "
	if(idx==tr[u].l&&tr[u].r==idx){
		return tr[u].val;
	}
	int mid=(tr[u].l+tr[u].r)>>1;
	pushdown(u);
	if(idx<=mid) return query(u<<1,idx);
	if(idx>mid) return query(u<<1|1,idx);
}
int main(){
   int t,q;
   cin>>t;
   for(int tt=1;tt<=t;tt++){
   		printf("Case #%d:\n",tt);
   		cin>>n;
   		idx=0;tim=0;
   		memset(tr,0,sizeof tr);
   		memset(h,-1,sizeof h);
   		memset(ne,-1,sizeof ne);
   		memset(st,0,sizeof st);
   		memset(ed,0,sizeof ed);
   		memset(e,0,sizeof e);
   		memset(du,0,sizeof du);
   		//memset(w,-1,sizeof w);
   		int u,v;
   		for(int i=1;i<=n-1;i++){
   			cin>>u>>v;
   			add(u,v);add(v,u);
   			du[u]++;
		}
		int k;
		for(k=1;k<=n;k++){
			if(du[k]==0) dfs(k,0);
		}
	
		build(1,1,n);
		cin>>q;

		char op[2];
		int x,y;
		int res;
		for(int i=1;i<=q;i++){
			cin>>op>>x;
			if(op[0]=='C'){
				res=query(1,st[x]);

				cout<<res<<endl;
			}else{
				cin>>y;
				change(1,st[x],ed[x],y);
			}
		}


   }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值