exam 2019-10-30

T1:AC
solution:

用樹狀數組維護前綴和,修改時暴力,用一個並查集維護當前點之後第一個不爲01的點是誰。。每次修改之後路徑壓縮一下並查集。
#include <bits/stdc++.h>
using namespace std;
const int maxn=500000+10;
long long ans[maxn],num[maxn],n,m;
void add(long long k,long long left,long long right){//to make a tree
	if(left==right){
		ans[k]=num[left];
		return ; 
	}
	long long mid=(left+right)>>1;
	add(k*2,left,mid);
	add(k*2+1,mid+1,right);
	ans[k]=ans[k*2]+ans[k*2+1];
}
long long query(int k,int lt,int rt,int qx,int qy){
	if(qx>rt||qy<lt)
		return 0;
	else{
		if(qx<=lt&&qy>=rt)
			return ans[k];
	}
	long long mid=(lt+rt)>>1;
	return query(k*2,lt,mid,qx,qy)+query(k*2+1,mid+1,rt,qx,qy); 
}
void line(long long k,long long  lt,long long rt,long long  qx,long long qy){
	if(ans[k]==rt-lt+1)//if lt-rt are full of 1,sqrt(1)=1,so it's ennesessary to continue(that's a very important branch-cutting) 
		return ;
    if(qy<lt||qx>rt)
		return ;
	else if(lt>=qx&&rt<=qy&&lt==rt){
        ans[k]=sqrt(ans[k]);//change
        return ;
    }
    else{
        long long mid=(lt+rt)/2;
		line(k*2,lt,mid,qx,qy);
        line(k*2+1,mid+1,rt,qx,qy);
        ans[k]=ans[k*2]+ans[k*2+1];
        return ;
    }
}
int main(){
	//freopen("game.in","r",stdin);
	//freopen("game.out","w",stdout);	
    cin>>n;
    for(int i=1;i<=n;i++)
    	scanf("%lld",&num[i]);
    	//cin>>num[i];
    add(1,1,n);
    cin>>m;
    for(int i=1;i<=m;i++){
        long long k,x,y;
        scanf("%lld%lld%lld",&k,&x,&y);
        if(k==0)
        	line(1,1,n,x,y);   
        else 
        	printf("%lld\n",query(1,1,n,x,y));
    }   
	return 0;
}

T2:WA
reason:Because the meaning of the question is to add the numbers into fewer groups,so I used kruskal to get some points…(only 80 points)
solution:

首先floyd傳遞閉包,求出兩兩點之間的轉移人員的代價。。然後枚舉出和爲0的飽和的選點集合。。。狀壓DP就行了。

T3:AC
sol

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