BUPT2014新生暑假个人排位赛08

来源:互联网 发布:淘宝贷款80万还不上 编辑:程序博客网 时间:2024/06/05 23:47

BOJ 448 游戏

计算几何
枚举每一条边,如果该边两侧的角有至少一个钝角,则计数
<pre name="code" class="cpp">#include <algorithm>#include <iostream>#include <iomanip>#include <cstring>#include <climits>#include <complex>#include <fstream>#include <cassert>#include <cstdio>#include <bitset>#include <vector>#include <deque>#include <queue>#include <stack>#include <ctime>#include <set>#include <map>#include <cmath>#define eps 1e-9 using namespace std;  template<class T>inline bool read(T &n){    T x = 0, tmp = 1; char c = getchar();    while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();    if(c == EOF) return false;    if(c == '-') c = getchar(), tmp = -1;    while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();    n = x*tmp;    return true;} //-----------------------------------------------------------------------typedef long long ll; struct point{    double x,y;    point(){}    point(double a,double b):x(a),y(b){}    friend point operator - (const point &a,const point &b)    {        return point(a.x-b.x,a.y-b.y);    }}a[1010]; double dot(const point &a,const point &b){    return a.x*b.x+a.y*b.y;} int main(){    int n;    while(read(n))    {        for(int i=1;i<=n;i++)        {            scanf("%lf %lf",&a[i].x,&a[i].y);        }        a[n+1]=a[1];a[0]=a[n];a[n+2]=a[2];        int ans=0;        for(int i=1;i<=n;i++)        {            point temp1=a[i+2]-a[i+1],temp2=a[i-1]-a[i];            point temp=a[i+1]-a[i];            //   a[ i ]   a[ i+1 ]  edge            if(dot(temp,temp2)<-eps||dot(temp,temp1)>eps)                ans++;        }        printf("%d\n",ans);    }    return 0;}

BOJ 468 小妹妹送快递

用所有的非DAG最短路都行,用最小生成树也行
最短路的松弛操作改成    dist[ next ] = min( dist[ next] , max( dist[ pre ] , e[ pre ][ next ].value ) )
Kruskal算法只需要维护到  fa[ 1 ] == fa[ n ]的情况,prim貌似维护完之后还要dfs遍历一次(而且我写的prim超时了)
SPFA版本
#include <algorithm>#include <iostream>#include <iomanip>#include <cstring>#include <climits>#include <complex>#include <fstream>#include <cassert>#include <cstdio>#include <bitset>#include <vector>#include <deque>#include <queue>#include <stack>#include <ctime>#include <set>#include <map>#include <cmath>#define INF 0x3f3f3f3f using namespace std;  template<class T>inline bool read(T &n){    T x = 0, tmp = 1; char c = getchar();    while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();    if(c == EOF) return false;    if(c == '-') c = getchar(), tmp = -1;    while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();    n = x*tmp;    return true;} //----------------------------------------------------------------------- const int MAXN=10010;const int MAXE=100010; struct Edge{    int to,next;    int v;}e[2*MAXE];int head[MAXN],tot=0,dist[MAXN];bool vis[MAXN];  int n,m; void addedge(int u,int v,int w){    e[tot].to=v;    e[tot].v=w;    e[tot].next=head[u];    head[u]=tot++;} void spfa(){    queue<int> que;    que.push(1);    vis[1]=true;    dist[1]=0;    while(!que.empty())    {        int u=que.front();        que.pop();        for(int i=head[u];i!=-1;i=e[i].next)        {            int maxn=max(e[i].v,dist[u]);            if(dist[e[i].to]>maxn)            {                dist[e[i].to]=maxn;                if(!vis[e[i].to])                {                    vis[e[i].to]=true;                    que.push(e[i].to);                }            }        }        vis[u]=false;    }} int main(){    int T;    read(T);    while(T--)    {       read(n);read(m);       tot=0;       memset(head,-1,sizeof(head));       memset(vis,0,sizeof(vis));       memset(dist,INF,sizeof(dist));       int u,v,w;       for(int i=1;i<=m;i++)       {           read(u);read(v);read(w);           if(u==1||v==n)               addedge(u,v,w);           else if(u==n||v==1)               addedge(v,u,w);           else           {               addedge(u,v,w);addedge(v,u,w);           }       }/*      for(int i=1;i<=n;i++)       {           cout<<i<<" : ";           for(int j=head[i];j!=-1;j=e[j].next)                cout<<e[j].to<<" ";            cout<<endl;       }*/       spfa();       if(dist[n]==0)            printf("%d\n",1);       else if(dist[n]==INF)            printf("shimatta!\n");       else            printf("%d\n",dist[n]);    }    return 0;}

Kruskal版本
#include <algorithm>#include <iostream>#include <iomanip>#include <cstring>#include <climits>#include <complex>#include <fstream>#include <cassert>#include <cstdio>#include <bitset>#include <vector>#include <deque>#include <queue>#include <stack>#include <ctime>#include <set>#include <map>#include <cmath>#define eps 1e-9#define INF 0x3f3f3f3f using namespace std;  template<class T>inline bool read(T &n){    T x = 0, tmp = 1; char c = getchar();    while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();    if(c == EOF) return false;    if(c == '-') c = getchar(), tmp = -1;    while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();    n = x*tmp;    return true;} //-----------------------------------------------------------------------const int MAXN=100010;struct Edge{int u,v,w;}e[MAXN];int n,m;int fa[10010];int find_fa(int x){if(fa[x]==x)return x;elsereturn fa[x]=find_fa(fa[x]);}void Merge(int x,int y){fa[x]=y;}bool cmp(Edge a,Edge b){return a.w<b.w;}int Kruskal(){sort(e+1,e+m+1,cmp);for(int i=1;i<=m;i++){int xx=find_fa(e[i].u);int yy=find_fa(e[i].v);if(xx!=yy){Merge(xx,yy); if(find_fa(1)==find_fa(n))return e[i].w;}}if(find_fa(1)!=find_fa(n))return INF;}int main(){int T;read(T);while(T--){read(n),read(m);for(int i=1;i<=n;i++)fa[i]=i; for(int i=1;i<=m;i++)read(e[i].u),read(e[i].v),read(e[i].w);int temp=Kruskal();if(temp==0)printf("1\n");else if(temp==INF)printf("shimatta!\n");elseprintf("%d\n",temp);}return 0;}

BOJ 472 学姐点名

签到题
卡代码长度,所以用了C写
将1~n求和,再将输入的 n-1个数求和,相减则是正确答案
#include<stdio.h> main(){    long long n;    while(~scanf("%lld",&n))    {        long long sum=n,temp,i;        for(i=1;i<n;i++)        {            scanf("%lld",&temp);            sum+=i-temp;        }        printf("%lld\n",sum);    }}


BOJ 452 解码锦标赛

DP
简直不敢相信的状态转移   i 表示第 i 个人, dep 表示第 dep 场比赛, dp 值表示胜利概率
dp[ i ][ dep ] = dp[ i ][ dep ] * sigma ( a[ i ][ j ]*dp[ j ][ dep-1 ] ) 其中 j 表示的在第 dep 场比赛可能与 i 碰面的队伍 ( j 的范围见代码
#include <algorithm>#include <iostream>#include <iomanip>#include <cstring>#include <climits>#include <complex>#include <fstream>#include <cassert>#include <cstdio>#include <bitset>#include <vector>#include <deque>#include <queue>#include <stack>#include <ctime>#include <set>#include <map>#include <cmath>#define EPS 1e-10#define INF 0x3f3f3f3f using namespace std;  template<class T>inline bool read(T &n){    T x = 0, tmp = 1; char c = getchar();    while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();    if(c == EOF) return false;    if(c == '-') c = getchar(), tmp = -1;    while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();    n = x*tmp;    return true;} //----------------------------------------------------------------------- const int MAXN=300; int n;double a[MAXN][MAXN]; double dp[MAXN][10];//win void solve(int dep){    int N=1<<dep;    N/=2;    for(int i=1;i<=n;i++)    {        int k=(i-1)/N;        double temp=0;        //cout<<i<<" :";        if(k&1)        {            for(int j=(k-1)*N+1;j<=k*N;j++)            {                temp+=a[i][j]*dp[j][dep-1];//cout<<j<<" "<<dp[j][dep-1]<<" ";            }            //cout<<endl;        }        else        {            for(int j=(k+1)*N+1;j<=(k+2)*N;j++)            {                temp+=a[i][j]*dp[j][dep-1];//cout<<j<<" "<<dp[j][dep-1]<<" ";            }             //cout<<endl;        }        dp[i][dep]=dp[i][dep-1]*temp;    }} int main(){ //   freopen("data.txt","r",stdin);    while(read(n)&&n)    {        int N=n,po=0;        double maxn=-1.0;        n=1<<n;        for(int i=1;i<=n;i++)            for(int j=1;j<=n;j++)                scanf("%lf",&a[i][j]);        for(int i=1;i<=n;i++)        {            if(i&1)                dp[i][1]=a[i][i+1];            else                dp[i][1]=a[i][i-1];            //cout<<" "<<dp[i][1];        }        //cout<<endl;        for(int i=2;i<=N;i++)            solve(i);        for(int i=1;i<=n;i++)        {            //cout<<dp[i][N]<<endl;            if((dp[i][N]-maxn)>EPS)            {                maxn=dp[i][N];                po=i;            }        }         printf("%d\n",po);    }    return 0;}

BOJ 451 田田的算数题

用线段树维护首项 x 与 公差 d
如果 首项 被截断在某一段区间外,而1操作修改又覆盖到了改区间,则将恰好被截断的那一部分即 x + ( mid - l + 1 ) * d 作为首项

#include <algorithm>#include <iostream>#include <iomanip>#include <cstring>#include <climits>#include <complex>#include <fstream>#include <cassert>#include <cstdio>#include <bitset>#include <vector>#include <deque>#include <queue>#include <stack>#include <ctime>#include <set>#include <map>#include <cmath>#define eps 1e-9#define INF 0x3f3f3f3f#define ll long long using namespace std; template<class T>inline bool read(T &n){    T x = 0, tmp = 1;    char c = getchar();    while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();    if(c == EOF) return false;    if(c == '-') c = getchar(), tmp = -1;    while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();    n = x*tmp;    return true;} template <class T>inline void write(T n){    if(n < 0)    {        putchar('-');        n = -n;    }    int len = 0,data[20];    while(n)    {        data[len++] = n%10;        n /= 10;    }    if(!len) data[len++] = 0;    while(len--) putchar(data[len]+48);}//----------------------------------- const int MAXN=100010; struct Node{    ll l,r;    ll sum;    ll x,d;      //x表示首项 , d表示公差}a[8*MAXN]; int n,m,num[MAXN]; void build(int idx, ll l, ll r){    a[idx].l=l,a[idx].r=r;    a[idx].sum=a[idx].x=a[idx].d=0;    if(l==r)    {        a[idx].sum=num[l];        return;    }    ll mid=l+((r-l)>>1);    build(idx<<1,l,mid);    build(idx<<1|1,mid+1,r);    a[idx].sum=a[idx<<1].sum+a[idx<<1|1].sum;} void pushdown(int idx){    ll l=a[idx].l,r=a[idx].r;    ll lc=idx<<1,rc=idx<<1|1,mid=l+((r-l)>>1);    a[lc].x+=a[idx].x;    a[rc].x+=a[idx].x+(mid-l+1)*a[idx].d;    a[lc].d+=a[idx].d;    a[rc].d+=a[idx].d;    a[idx].sum+=a[idx].x*(r-l+1);    a[idx].sum+=(r-l+1)*(r-l)/2*a[idx].d;    a[idx].x=a[idx].d=0;}  //如果标记相同则下推void update(int idx,ll L,ll R,int x,int d){    ll l=a[idx].l,r=a[idx].r;    ll lc=idx<<1,rc=idx<<1|1,mid=l+((r-l)>>1);    if(l==L&&r==R)    {        a[idx].x+=x;        a[idx].d+=d;        return;    }    pushdown(idx);                //标记下放同时更新    if(R<=mid)  update(lc,L,R,x,d);    else if(L>mid)  update(rc,L,R,x,d);    else    {        update(lc,L,mid,x,d);        update(rc,mid+1,R,x+d*(mid-L+1),d);    }    a[idx].sum+=x*(R-L+1)+(R-L+1)*(R-L)/2*d;} ll query(int idx,int L,int R){    ll l=a[idx].l,r=a[idx].r;    ll mid=l+((r-l)>>1);    ll ret=(a[idx].x*2+(L+R-l*2)*a[idx].d)*(R-L+1)/2;    if(l==L&&r==R)    {        pushdown(idx);        return a[idx].sum;    }    if(R<=mid)        return ret+query(idx<<1,L,R);    if(L>mid)        return ret+query(idx<<1|1,L,R);    return ret+query(idx<<1,L,mid)+query(idx<<1|1,mid+1,R);} int main(){    int T,t,l,r,x,d;    read(T);    while(T--)    {        read(n),read(m);        for(int i=1;i<=n;i++)            read(num[i]);        build(1,1,n);/*        for(int i=1;i<=2*n+1;i++)            printf("%d : (%d->%d)  %d\n",i,a[i].l,a[i].r,a[i].sum);*/        while(m--)        {            read(t),read(l),read(r);            if(t==1)            {                read(x),read(d);                update(1,l,r,x,d); /*               for(int i=1;i<=2*n+1;i++)                    printf("%d : (%d->%d)  %d\n",i,a[i].l,a[i].r,a[i].sum);*/            }            else            {                ll ans=query(1,l,r);                write(ans);                putchar('\n');            }        }    }    return 0;}

下面为桶分法的代码
将 1~n 区间按照 sqrt( n )的大小分块
在整块内就统一加减,用同样的方法维护 x 和 d ,然后边缘部分暴力加
感谢 刘玮 的代码
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#define MAX_N 100005using namespace std;typedef long long LL;const int sib=100;int N,M;LL A[100005],B[1000],Bhead[1000],Bdif[1000];void add(int a,int b,LL x,LL d){    int i,j;    int bl=a/sib,br=b/sib;//  a=a%sib;//  b=b%sib;    LL res=0;    for(i=a; i<bl*sib+sib&&i<=b; i++)    {        A[i]=A[i]+x+(i-a)*d;        B[i/sib]+=x+(i-a)*d;        res+=d;    }//   printf("%d %d res:%lld\n",a,i-1,res);    //printf("res:%lld\n",res);    for(j=bl+1; j<br; j++)    {        Bhead[j]=Bhead[j]+x+res;        Bdif[j]=Bdif[j]+d;        B[j]+=(x+res)*sib+sib*(sib-1)/2*d;        //   printf("%d %d\n",x+res,sib);        // printf("add B[%d] :%lld\n",j,(x+res)*sib+sib*(sib-1)/2*d);        res+=sib*d;        //  printf("Bhead[%d]=%d ",j,Bhead[j]);        //  printf("Bdif[%d]=%d\n",j,Bdif[j]);    }    // printf("tail:%d %d res:%d\n",br*sib,b,res);    if(bl!=br)        for(i=br*sib; i<=b; i++)        {            B[i/sib]+=x+d*(i-a);            A[i]+=x+d*(i-a);            //  printf("add:A[%d]=%lld\n",i,A[i]);        }}LL sum(int a,int b){    int i,j;    int bl=a/sib,br=b/sib;    LL res=0;    for(i=a; i<(bl+1)*sib&&i<=b; i++)    {        // printf("A[%d]=%lld ",i,A[i]);        res+=A[i];        //  printf("B:%lld\n",Bhead[bl]+(i%sib)*Bdif[bl]);        res+=Bhead[bl]+(i%sib)*Bdif[bl];    }    for(i=bl+1; i<br; i++)    {        // printf("B[%d]:%lld\n",i,B[i]);        res+=B[i];    }    // printf("l:%d r:%d\n",bl,br);    if(br!=bl)        for(i=br*sib; i<=b; i++)        {            res+=A[i];            //   printf("A[%d]=%lld ",i,A[i]);            res+=Bhead[br]+(i%sib)*Bdif[br];            //  printf("B:%lld\n",Bhead[br]+(i%sib)*Bdif[br]);        }    return res;}int main(){    int i,j,k,T,l,r,flag,x,d;    scanf("%d",&T);    while(T--)    {        scanf("%d%d",&N,&M);        memset(B,0,sizeof(B));        memset(Bhead,0,sizeof(Bhead));        memset(Bdif,0,sizeof(Bdif));        for(i=0; i<N; i++)        {            scanf("%lld",&A[i]);            B[i/sib]+=A[i];        }        for(i=0; i<M; i++)        {            scanf("%d %d %d",&flag,&l,&r);            if(flag==1)            {                scanf("%d %d",&x,&d);                add(l-1,r-1,(LL)x,(LL)d);                /* for(j=0;j<N/sib;j++){                       printf("B[%d]=%lld ",j,B[j]);                   }                   printf("\n");*/            }            else if(flag==2)            {                /*for(j=0;j<N/sib;j++){                    printf("B[%d]=%lld ",j,B[j]);                }                printf("\n");*/                printf("%lld\n",sum(l-1,r-1));            }            //  printf("flag:%d\n",flag);        }    }    return 0;}
树状数组版
感谢楠哥的代码提供
#include <iostream>#include <string>#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <algorithm>#include <queue>#include <vector>#define N 100005using namespace std;typedef long long ll;ll ans;ll A[N],B[N],C[N],D[N],E[N];ll n;ll lowbit(ll x){    return x&(-x);}void Update(ll x,ll det,ll a[]){    for (ll i = x;i<= n; i+=lowbit(i))        a[i]+=det;}ll GetSum(ll x,ll a[]){    ll res=0;    for (ll i=x;i>0;i-=lowbit(i))        res+=a[i];    return res;}ll dGetSum(ll n){    ll res=0;    res=(n+1)*(n+1)*GetSum(n,C)+((n+1)*GetSum(n-1,D)-(3*n+4)*GetSum(n,D)+GetSum(n,E)-n*(n+1)*GetSum(n-1,C))/2;    return res;}ll xGetSum(ll n){    ll res=0;    res=(n+1)*GetSum(n,A)-GetSum(n,B);    return res;}int main(){    int T;    cin>>T;    while(T--)    {        ll m,num1=0;        scanf("%lld%lld",&n,&m);        memset(A,0,sizeof(long long)*(n+2));        memset(B,0,sizeof(long long)*(n+2));        memset(C,0,sizeof(long long)*(n+2));        memset(D,0,sizeof(long long)*(n+2));        memset(E,0,sizeof(long long)*(n+2));        for (ll i=1;i<=n;i++)        {            ll num;            scanf("%lld",&num);            Update(i,num-num1,A);            Update(i,i*(num-num1),B);            num1=num;        }        for (ll i=1;i<=m;i++)        {            ll order;            scanf("%d",&order);            if ( order==1 )            {                ll l,r,x,d;                scanf("%lld%lld%lld%lld",&l,&r,&x,&d);                Update(l,x,A);                Update(l,l*x,B);                Update(r+1,-x,A);                Update(r+1,-(r+1)*x,B);                if (r>l)                {                    Update(l+1,d,C);                    Update(r+1,-(r-l+1)*d,C);                    Update(r+2,(r-l)*d,C);                    Update(l+1,(l+1)*d,D);                    Update(r+1,-(r-l+1)*(r+1)*d,D);                    Update(r+2,(r-l)*(r+2)*d,D);                    Update(l+1,(l+1)*(l+1)*d,E);                    Update(r+1,-(r+1)*(r+1)*(r-l+1)*d,E);                    Update(r+2,(r-l)*(r+2)*(r+2)*d,E);                }            }            else if( order==2 )            {                ll l,r;                scanf("%lld%lld",&l,&r);                ans=xGetSum(r)-xGetSum(l-1)+dGetSum(r)-dGetSum(l-1);                printf("%lld\n",ans);            }        }    }}



0 0
原创粉丝点击