现在的位置: 首页 > 综合 > 正文

CUGBACM_Summer_Tranning2【二维线段树】

2018年04月24日 ⁄ 综合 ⁄ 共 5442字 ⁄ 字号 评论关闭

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 0x7FFFFFFF
typedef 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|1

int 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

传送门

抱歉!评论已关闭.