2019 2 16 总结

T1


找规律,得到规律

联立得

结束

#include<bits/stdc++.h>
using namespace std;long long n;int main(){cin>>n;if(n<=31) cout<<(1ll<<n)-1;else cout<<(long long)(n*(log(2)/log(10)));}

T2

每个人有四个数字,朋友的定义是两人至少有一个数字相同,求每个人与左边的人有几个朋友,数字<=50
因为数字很小,直接开四维数组统计,根据小学奥数思想,最终答案应是calc1()-calc2()+calc3()-calc4()

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
    int num=0,fs=1;
    char ch;
    while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if(ch=='-') fs=-1,ch=getchar();
    while(ch>='0'&&ch<='9') num=num*10+ch-'0',ch=getchar();
    return num*fs;
}
int n,a[100009][5];
int tot1[51],tot2[51][51],tot3[51][51][51],tot4[51][51][51][51];
int ans;
int main ()
{
    //freopen("friend.in","r",stdin);
    //freopen("friend.out","w",stdout);
    n=read();
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=4;j++)
        {
            a[i][j]=read();
        }
        sort(a[i]+1,a[i]+5);
        ans=0;
        for(int j=1;j<=4;j++)
        {
            ans+=tot1[a[i][j]]; 
        }
        for(int j=1;j<=3;j++)
        {
            for(int k=j+1;k<=4;k++)
            {
                ans-=tot2[a[i][j]][a[i][k]];
            }
        }
        for(int a1=1;a1<=2;a1++)
        {
            for(int a2=a1+1;a2<=3;a2++)
            {
                for(int a3=a2+1;a3<=4;a3++)
                {
                    ans+=tot3[a[i][a1]][a[i][a2]][a[i][a3]];    
                }
            }
        }
        ans-=tot4[a[i][1]][a[i][2]][a[i][3]][a[i][4]];
        printf("%d\n",ans);
        for(int j=1;j<=4;j++)
        {
            tot1[a[i][j]]++;    
        }
        for(int j=1;j<=3;j++)
        {
            for(int k=j+1;k<=4;k++)
            {
                tot2[a[i][j]][a[i][k]]++;
            }
        }
        for(int a1=1;a1<=2;a1++)
        {
            for(int a2=a1+1;a2<=3;a2++)
            {
                for(int a3=a2+1;a3<=4;a3++)
                {
                    tot3[a[i][a1]][a[i][a2]][a[i][a3]]++;   
                }
            }
        }
        tot4[a[i][1]][a[i][2]][a[i][3]][a[i][4]]++;
    }
    return 0;   
}

拓展:当k增大时,可以使用散列表进行统计

T3

裸的背包,不说了

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
    int num=0,fs=1;
    char ch;
    while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if(ch=='-') fs=-1,ch=getchar();
    while(ch>='0'&&ch<='9') num=num*10+ch-'0',ch=getchar();
    return num*fs;
}
int m,n,a[309],b[309],ans=1;
int f[1009][1009]; 
int main ()
{
    //freopen("psolve.in","r",stdin);
    //freopen("psolve.out","w",stdout);
    m=read(),n=read();
    memset(f,-1,sizeof(f));
    f[1][m]=0;
    for(int i=1;i<=n;i++)
    {
        a[i]=read(),b[i]=read();
    }
    while(1)
    {
        //cout<<ans<<endl;
        for(int i=0;i<=m;i++)
        {
            if(f[ans][i]==-1) continue;
            f[ans+1][m]=max(f[ans+1][m],f[ans][i]);
            int nowcost=0,ntcost=0;
            for(int k=1;f[ans][i]+k<=n;k++)
            {
                nowcost+=a[f[ans][i]+k],ntcost+=b[f[ans][i]+k];
                if(nowcost<=i&&ntcost<=m)
                {
                    //if(f[ans][i]+k>f[ans+1][m-ntcost]) cout<<ans+1<<" "<<m-ntcost<<" "<<f[ans][i]+k<<endl;
                    f[ans+1][m-ntcost]=max(f[ans+1][m-ntcost],f[ans][i]+k);
                    if(f[ans+1][m-ntcost]==n) 
                    {
                        printf("%d",ans+2);
                        return 0;   
                    }
                }
                else break;
            }
        }
        ans++;
    }
    return 0;   
}

T4

给定一棵树,每个点都有权值,查询在根为k的情况下节点x的子树权值和
分块,将sqrt(n)作为块大小,将一块点看作一个点,这样的话查询就分为块内查询,块外查询,块内统计,块外统计四部分,代码很长,但很好想,而且该算法优点很大(拓展的时候讲)

#include<bits/stdc++.h>
using namespace std;
int n,m;
int blong[100009],block,lenblock[100009],blockbh=1;
int fto[100009],f[100009];
int head[100009],to[200009],nt[200009],bh;
int bkhead[100009],bkto[100009],bknt[100009],bkfrom[100009],bknext[100009],bkbh;
int val[100009];
int nowroot=1;
int ans;
bool hasbkfinden,hasfinden;
int superx;
inline int read()
{
    int num=0,fs=1;
    char ch;
    while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if(ch=='-') fs=-1,ch=getchar();
    while(ch>='0'&&ch<='9') num=num*10+ch-'0',ch=getchar();
    return num*fs;
}
inline void add(int u,int v)
{
    bh++;
    nt[bh]=head[u];
    head[u]=bh;
    to[bh]=v;   
}
inline void bkadd(int u,int v,int x,int y)
{
    bkbh++;
    bknt[bkbh]=bkhead[u];
    bkhead[u]=bkbh;
    bkto[bkbh]=v;   
    bkfrom[bkbh]=x;
    bknext[bkbh]=y;
}
void dfs2(int now,int fa)
{
    if(lenblock[blong[fa]]>block) blockbh++;
    blong[now]=blockbh;
    lenblock[blockbh]++;
    f[blockbh]+=val[now];
    for(int i=head[now];i;i=nt[i])
    {
        if(to[i]!=fa)
        {
            dfs2(to[i],now);
        }
    }
}
void dfs3(int now,int fa)
{
    for(int i=head[now];i;i=nt[i])
    {
        if(to[i]!=fa&&blong[to[i]]!=blong[now])
        {
            bkadd(blong[to[i]],blong[now],to[i],now);
            bkadd(blong[now],blong[to[i]],now,to[i]);
            //cout<<now<<" "<<to[i]<<" %%%"<<endl;
            fto[to[i]]=blong[now];
            fto[now]=blong[to[i]];
            dfs3(to[i],now);
        }
        else if(to[i]!=fa) dfs3(to[i],now);
    }
}
void bkdfs(int now,int fa)
{
    ans+=f[now];
    for(int i=bkhead[now];i;i=bknt[i])
    {
        if(bkto[i]!=fa)
        {
            bkdfs(bkto[i],now);
        }
    }
}
void dfs(int now,int fa)
{
    //cout<<now<<" @@@"<<endl;
    ans+=val[now];
    for(int i=head[now];i;i=nt[i])
    {
        if(to[i]!=fa)
        {
            if(blong[to[i]]!=blong[now])
            {
                //cout<<blong[to[i]]<<" "<<blong[now]<<" &&&"<<endl;
                bkdfs(blong[to[i]],blong[now]); 
            }
            else
            {
                dfs(to[i],now);
            }
        }
    }
}
void ffind(int now,int fa,int k)
{
    if(hasfinden) return;
    if(now==k)
    {
        hasfinden=1;
        dfs(now,fa);
        return;
    }
    for(int i=head[now];i;i=nt[i])
    {
        if(to[i]!=fa)
        {
            if(to[i]==k)
            {
                hasfinden=1;
                //cout<<to[i]<<" "<<now<<" !!!"<<endl;
                dfs(to[i],now);     
            }
            ffind(to[i],now,k);
            if(hasfinden) return;
        }
    }
}
void bkfind(int now,int fa,int k)
{
    for(int i=bkhead[now];i;i=bknt[i])
    {
        if(bkto[i]!=fa)
        {
            if(bkto[i]==k)
            {
                //cout<<bknext[i]<<" "<<bkfrom[i]<<" "<<superx<<endl;
                hasbkfinden=1;
                ffind(bknext[i],bkfrom[i],superx);  
            }
            bkfind(bkto[i],now,k);
            if(hasbkfinden) return;
        }
    }
}
int main ()
{
    //freopen("transform.in","r",stdin);
    //freopen("transform.out","w",stdout);
    n=read(),m=read();
    block=sqrt(n)*1.6;
    for(int i=1;i<n;i++)
    {
        int u=read(),v=read();
        add(u,v);
        add(v,u);   
    }
    for(int i=1;i<=n;i++)
    {
        val[i]=read();
    }
    dfs2(1,0);
    dfs3(1,0);
    /*for(int i=1;i<=n;i++)
    {
        cout<<blong[i]<<" ";    
    }
    cout<<endl;*/
    nowroot=read();
    for(int i=1,opt,x;i<=m;i++)
    {
        opt=read(),x=read();
        superx=x;
        if(opt==1)
        {
            nowroot=x;
        }
        else
        {   
            ans=0;
            hasbkfinden=hasfinden=0;
            if(blong[nowroot]!=blong[x])
            {
                bkfind(blong[nowroot],0,blong[x]);  
            }
            else 
            {
                ffind(nowroot,0,x); 
            }
            printf("%d\n",ans);
        }
    }
    return 0;   
}

拓展:
1、增加区间修改权值
2、改变连边


  转载请注明: wenjing233的小站 2019 2 16 总结

 上一篇
2019 2 15 总结 2019 2 15 总结
T1【简要题面】有n个商品,实际价格为ai,价值是ci,需要口袋中钱≥bi时才可以购买。现在你有m元,求可以购买到的最大价值。n<=500,m<=5000考场的时候按b从大到小排序然后被hack了,然后就耍小聪明在昨晚一遍后把序
下一篇 
2019 2 17 总结 2019 2 17 总结
T1题意:给出n,求1到n内有几个数与n的最大公约数不为1(n<=10000000)直接分解质因数容斥即可 #include<bits/stdc++.h> using namespace std; const long long