CUGBACM_Summer_Tranning2【二维线段树】

来源:互联网 发布:png软件下载 编辑:程序博客网 时间:2024/06/04 19:14

HDU 4813

水题

#include<cstring>#include<string>#include<fstream>#include<iostream>#include<iomanip>#include<cstdio>#include<cctype>#include<algorithm>#include<queue>#include<map>#include<set>#include<vector>#include<stack>#include<ctime>#include<cstdlib>#include<functional>#include<cmath>using namespace std;#define PI acos(-1.0)#define MAXN 100005#define eps 1e-8#define INF 0x7FFFFFFFtypedef long long ll;char s[1005];int main(){    int n,m,t,i;    cin>>t;    while(t--){        cin>>n>>m;        if(n>m){            int tt = n;            n = m;            m = tt;        }        cin>>s;        int k = 0;        int l = strlen(s);        for(i=0;i<n;i++){            for(int j =0;j<m;j++){                cout<<s[k++];            }            cout<<endl;        }    }    return 0;}


HDU 4814

题意:把一个n进制数转换为[(1+√5)/2]进制

根据题目给的两个公式,011->100,0200->1001可以推广到 [0][n][0][0]->[n/2][n%2][0][n/2],由于[(1+√5)/2]^50 > 10^10,所以数组开100个就够了,小数点前小数点后各50个数字。开始时把n放在数组第50位,则最多进行50次循环的变换就能变为0、1组成的形式。

#include<cstring>#include<string>#include<fstream>#include<iostream>#include<iomanip>#include<cstdio>#include<cctype>#include<algorithm>#include<queue>#include<map>#include<set>#include<vector>#include<stack>#include<ctime>#include<cstdlib>#include<functional>#include<cmath>using namespace std;#define PI acos(-1.0)#define MAXN 100005#define eps 1e-7#define INF 0x7FFFFFFF#define ff sqrt(5.0)typedef long long ll;int a[110];int main(){    int n,i,flag;    while(scanf("%d",&n)!=EOF){        if(n==1){            cout<<1<<endl;            continue;        }        memset(a,0,sizeof(a));        a[50] = n;        flag = 1;        while(flag){            flag = 0;            for(i=105;i>=1;i--){                if(a[i]>1){                    flag = 1;                    a[i-1] += a[i]/2;                    a[i+2] += a[i]/2;                    a[i] %= 2;                }            }            for(i=105;i>=2;i--){                if(a[i]&&a[i-1]){                    flag = 1;                    int temp = min(a[i],a[i-1]);                    a[i-2] += temp;                    a[i] -= temp;                    a[i-1] -= temp;                }            }        }        int ll, rr;        for(i=0;i<110;i++){            if(a[i]){                ll = i;                break;            }        }        for(i=105;i>0;i--){            if(a[i]){                rr = i;                break;            }        }        for(i=ll;i<=rr;i++){            cout<<a[i];            if(i==50)   cout<<".";        }        cout<<endl;    }    return 0;}


HDU 4815

有n个问题各有不同的分值,两个人回答问题,假设B答对每道题的概率为0.5,问A至少得多少分才能使不输给B的概率不小于P。

这个思路是别人博客中摘的:我们要算A不输给B的概率。如果我们知道A得每种得分的频数y。和A不小于B得分的频数x.那么p=x/y。先只需x/y>=p。x>=y*p。就行了。因为答每到题有两种可能。所以B得分就有y=2^n种可能。现在关键就是求x了。要使得分最小。我们可以先用背包求出B得每种得分的方案数。让后得分从小到大累加方案数。第一个使得x>=y*p的得分就是最小得分。

#include<cstring>#include<string>#include<fstream>#include<iostream>#include<iomanip>#include<cstdio>#include<cctype>#include<algorithm>#include<queue>#include<map>#include<set>#include<vector>#include<stack>#include<ctime>#include<cstdlib>#include<functional>#include<cmath>using namespace std;#define PI acos(-1.0)#define MAXN 100005#define eps 1e-7#define INF 0x7FFFFFFF#define ff sqrt(5.0)typedef long long ll;int dp[40010],score[50];int main(){    int n,t,i;    ll m;    double p;    ll cnt,sum;    scanf("%d",&t);    while(t--){        memset(dp,0,sizeof(dp));        sum = cnt = 0;        scanf("%d%lf",&n,&p);        m = 1LL<<n;        dp[0] = 1;        for(i=0;i<n;i++){            scanf("%d",&score[i]);            sum += score[i];        }        for(i=0;i<n;i++){            for(int j=sum;j>=score[i];j--){                if(dp[j-score[i]])  dp[j] += dp[j-score[i]];            }        }        ll x = ceil(p*m);        for(i=0;i<=sum;i++){            cnt += dp[i];            if(cnt>=x){                cout<<i<<endl;                break;            }        }    }    return 0;}


HDU 4819

二维线段树。做的时候虽然感觉像一个二维的线段树不过还是勇敢的T了一发。二维线段树不会,网上没找到讲解,找了个代码先当模板用。一直在想二维的树是怎么建的,看了代码感觉行被当做一个索引,在每个列上建一个树,每一个树上还是父节点保存着子节点的最大最小值,查询的时候像和一维的思路类似,只不过要先从行序列开始找。

#include<cstring>#include<string>#include<fstream>#include<iostream>#include<iomanip>#include<cstdio>#include<cctype>#include<algorithm>#include<queue>#include<map>#include<set>#include<vector>#include<stack>#include<ctime>#include<cstdlib>#include<functional>#include<cmath>using namespace std;#define PI acos(-1.0)#define MAXN 810#define eps 1e-7#define INF 0x7FFFFFFF#define ff sqrt(5.0)typedef long long ll;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1int ds[MAXN<<2][MAXN<<2];int db[MAXN<<2][MAXN<<2];int n;int A[MAXN][MAXN];struct node{    int minm,maxm;};void pushup(int k,int rt){    db[k][rt]=max(db[k][rt<<1],db[k][rt<<1|1]);    ds[k][rt]=min(ds[k][rt<<1],ds[k][rt<<1|1]);    for (int i=(k>>1);i;i>>=1){        db[i][rt]=max(db[i<<1][rt],db[i<<1|1][rt]);        ds[i][rt]=min(ds[i<<1][rt],ds[i<<1|1][rt]);    }}void buildc(int k,int l,int r,int rt){    db[k][rt]=-INF;    ds[k][rt]=INF;    if (l>=r){        return;    }    int m=(l+r)>>1;    buildc(k,lson);    buildc(k,rson);}void buildr(int l,int r,int rt){    buildc(rt,1,n,1);    if (l>=r){        return;    }    int m=(l+r)>>1;    buildr(lson);    buildr(rson);}node queryc(int k,int c1,int c2,int l,int r,int rt){    if (c1<=l && r<=c2){        node x;        x.maxm=db[k][rt];        x.minm=ds[k][rt];        return x;    }    int m=(l+r)>>1;    if (m<c1){        return queryc(k,c1,c2,rson);    }    else    if (m>=c2){        return queryc(k,c1,c2,lson);    }    else{        node a=queryc(k,c1,c2,lson);        node b=queryc(k,c1,c2,rson);        node c;        c.minm=min(a.minm,b.minm);        c.maxm=max(a.maxm,b.maxm);        return c;    }}node queryr(int r1,int r2,int c1,int c2,int l,int r,int rt){    if (r1<=l && r<=r2)    {        return queryc(rt,c1,c2,1,n,1);    }    int m=(l+r)>>1;    if (r2<=m){        return queryr(r1,r2,c1,c2,lson);    }    else    if (r1>m){        return queryr(r1,r2,c1,c2,rson);    }    else{        node a=queryr(r1,r2,c1,c2,lson);        node b=queryr(r1,r2,c1,c2,rson);        node c;        c.maxm=max(a.maxm,b.maxm);        c.minm=min(a.minm,b.minm);        return c;    }}void updatec(int val,int k,int C,int l,int r,int rt){    if (l>=r)    {        db[k][rt]=val;        ds[k][rt]=val;        for (int i=(k>>1);i;i>>=1){            db[i][rt]=max(db[i<<1][rt],db[i<<1|1][rt]);            ds[i][rt]=min(ds[i<<1][rt],ds[i<<1|1][rt]);        }        return;    }    int m=(l+r)>>1;    if (C<=m) updatec(val,k,C,lson);    else updatec(val,k,C,rson);    pushup(k,rt);}void updater(int val,int R,int C,int l,int r,int rt){    if (l>=r)    {        updatec(val,rt,C,1,n,1);        return;    }    int m=(l+r)>>1;    if (R<=m) updater(val,R,C,lson);    else updater(val,R,C,rson);}int main(){    int t,k = 1,m,ll,rr,ss,i;    scanf("%d",&t);    while (t--)    {        scanf("%d",&n);        buildr(1,n,1);        for (i=1;i<=n;i++){            for (int j=1;j<=n;j++){                scanf("%d",&A[i][j]);                updater(A[i][j],i,j,1,n,1);            }        }        scanf("%d",&m);        printf("Case #%d:\n",k++);        int r1,r2,c1,c2;        for(i=0;i<m;i++)        {            scanf("%d%d%d",&ll,&rr,&ss);            r1=max(ll-ss/2,1);            r2=min(ll+ss/2,n);            c1=max(rr-ss/2,1);            c2=min(rr+ss/2,n);            node ans=queryr(r1,r2,c1,c2,1,n,1);            int ret=(ans.maxm+ans.minm)/2;            printf("%d\n",ret);            updater(ret,ll,rr,1,n,1);        }    }    return 0;}


HDU 4821

传送门

0 0
原创粉丝点击