2013 ACM/ICPC Asia Regional Online —— Warmup2

HDU 4716  A Computer Graphics Problem 

水题。略

 

HDU 4717 The Moving Points

题目:给出n个点的起始位置以及速度矢量,问任意一个时刻使得最远的两点的距离最小。

分析:显然只有两点的话,答案满足三分性质。对于多个点,画个图分析一下,其实也满足三分性质。因此,先构造n*(n-1)/2个二次函数,于是三分枚举时间即可。

 

#include <iostream>

#include <cstdio>

#include <cstring>

#include <cmath>

#include <algorithm>

#include <vector>

#include <map>

#include <stack>

#include <queue>



using namespace std;



#define pb push_back

#define mp make_pair

#define eps 1e-6

typedef long long ll;



struct point {

    ll x, y, vx, vy;

} p[350];



struct func {

    ll a, b, c;

} f[50000];

int m, n;

double anst, ansd;

inline void makef(point a, point b) {

    f[m].a = (a.vx-b.vx)*(a.vx-b.vx)+(a.vy-b.vy)*(a.vy-b.vy);

    f[m].b = 2*((a.x-b.x)*(a.vx-b.vx)+(a.y-b.y)*(a.vy-b.vy));

    f[m++].c = (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);

}

inline double foo(int x, double t) {

    return f[x].a*t*t+f[x].b*t+f[x].c;

}

inline double getd(double t) {

    double ret = -1;

    for (int i = 0; i < m; ++i) {

        double tmp = foo(i,t);

        if (tmp > ret) ret = tmp;

    }

    return ret;

}

int main() {

#ifndef ONLINE_JUDGE

    freopen("sum.in", "r", stdin);

    // freopen("cf.out", "w", stdout);

#endif



    int T;

    scanf("%d", &T);

    for (int ncase = 1; ncase <= T; ++ncase) {

        scanf("%d", &n);

        for (int i = 0; i < n; ++i)

            scanf("%I64d%I64d%I64d%I64d",&p[i].x, &p[i].y, &p[i].vx, &p[i].vy);

        m = 0;

        for (int i = 0; i < n-1; ++i)

            for (int j = i+1; j < n; ++j)

                makef(p[i], p[j]);

        double low = .0, high = 1e120;

        while(high-low>eps) {

            double mid1 = (2*low+high)/3.0;

            double mid2 = (low+2*high)/3.0;

            double tmp1 = getd(mid1);

            double tmp2 = getd(mid2);

            if (tmp1-tmp2>eps) {

                anst = mid2;

                ansd = tmp2;

                low = mid1;

            } else {

                anst = mid1;

                ansd = tmp1;

                high = mid2;

            }

        }

        printf("Case #%d: %.2lf %.2lf\n", ncase, anst, sqrt(ansd));

    }



    return 0;

}

 

  

 

 

HDU 4718 The LCIS on the Tree

我用的是树链剖分+线段树来写,发现在求lca合并时很难维护,改天用lct水掉算了 >.<

这题的简单版 hdu 3308 LCIS 线段树

 

待补。

 

HDU 4719  Oh My Holy FFF

题目大意:给出n个数b1...bn,现在需要划分集合,每个集合的元素不能超过L个,并且要求第i个集合的最后一个元素now大于第i-1个集合的最后一个元素pre。每个集合的价值为:now*now-pre。题目目标是:求max{ sigma(所有集合价值) }

分析:不难想出一个递推式:dp[i]表示当前i作为集合的最后一个元素的最优解。

dp[i] = max{  dp[j] + b[i]*b[i]-b[j]  }。 0<=i-j<= L,b[j]<b[i]。

注意到b[i]是不变的,于是转移方程可以写成:

dp[i] = max{  b[i]*b[i]  + (dp[j] -b[j])  }。  0<=i-j<= L,b[j]<b[i]。

如何在约束( 0<=i-j<= L,b[j]<b[i] ) 下,求出dp[j]-b[j]最大?

这里可以用到单调队列,线段树维护一下即可。

具体实现(代码)献上我队友的代码吧 = =。

 

struct seg {

        int l,r;

        ll mx;

        int mid() {

                return l+r>>1;

        };

} tree[maxn<<2];

void init_tree(int l,int r,int x)

{

        tree[x].l=l,tree[x].r=r;

        tree[x].mx=-1;

        if(l==r)return;

        int mid=l+r>>1;

        init_tree(l,mid,lc(x));

        init_tree(mid+1,r,rc(x));

}

void insert(int pos,int x,ll num)

{

        if(tree[x].l==tree[x].r) {

                tree[x].mx=num;

                return;

        }

        int mid=tree[x].mid();

        if(pos<=mid)insert(pos,lc(x),num);

        else insert(pos,rc(x),num);

        tree[x].mx=max(tree[lc(x)].mx,tree[rc(x)].mx);

}

ll query(int l,int r,int x)

{

        if(l<=tree[x].l && tree[x].r<=r)

                return tree[x].mx;

        int mid=tree[x].mid();

        ll res=-1;

        if(l<=mid)res=max(res,query(l,r,lc(x)));

        if(r>mid)res=max(res,query(l,r,rc(x)));

        return res;

}

deque<pair<ll,int> >q[maxn];

int t,n,m,cas;

ll a[maxn];

int main()

{

        cin>>t;

        while(t--) {

                scanf("%d%d",&n,&m);

                init_tree(0,100000,1);

                for(int i=0; i<=100000; i++)

                        while(!q[i].empty())q[i].pop_front();

                ll ans=-1;

                for(int i=1; i<=n; i++)

                        scanf("%I64d",&a[i]);

                for(int i=1; i<=n; i++) {

                        ll res=query(0,a[i]-1,1);

                        if (i <= m && res==-1)res=0;

                        if(res!=-1) {

                                res+=a[i]*a[i];

                                if(i==n)ans=res;



                                while(!q[a[i]].empty() && q[a[i]].back().first<=res-a[i])

                                        q[a[i]].pop_back();

                                q[a[i]].push_back(mp(res-a[i],i));

                                if(q[a[i]].front().second==i)

                                        insert(a[i],1,q[a[i]].front().first);

                        }





                        if(i>m) {

                                insert(a[i-m],1,-1);

                                if(q[a[i-m]].size() && q[a[i-m]].front().second==i-m)

                                        q[a[i-m]].pop_front();

                                if(!q[a[i-m]].empty())

                                        insert(a[i-m],1,q[a[i-m]].front().first);

                        }

                }

                if(ans!=-1)printf("Case #%d: %I64d\n",++cas,ans);

                else printf("Case #%d: No solution\n",++cas);

        }

}

 

  

 

 

 

HDU 4720 Naive and Silly Muggles

注意到不一定是外接圆,如果是钝角三角形时,最长边即为直径。

 

#include <set>

#include <map>

#include <list>

#include <cmath>

#include <queue>

#include <stack>

#include <string>

#include <vector>

#include <cstdio>

#include <cstring>

#include <iostream>

#include <algorithm>



using namespace std;



typedef long long ll;

typedef unsigned long long ull;



#define debug puts("here")

#define rep(i,n) for(int i=0;i<n;i++)

#define rep1(i,n) for(int i=1;i<=n;i++)

#define REP(i,a,b) for(int i=a;i<=b;i++)

#define foreach(i,vec) for(unsigned i=0;i<vec.size();i++)

#define pb push_back

#define RD(n) scanf("%d",&n)

#define RD2(x,y) scanf("%d%d",&x,&y)

#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)

#define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w)

#define All(vec) vec.begin(),vec.end()

#define MP make_pair

#define PII pair<int,int>

#define PQ priority_queue

#define cmax(x,y) x = max(x,y)

#define cmin(x,y) x = min(x,y)

#define Clear(x) memset(x,0,sizeof(x))

/*



#pragma comment(linker, "/STACK:1024000000,1024000000")



int size = 256 << 20; // 256MB

char *p = (char*)malloc(size) + size;

__asm__("movl %0, %%esp\n" :: "r"(p) );



*/



char IN;

bool NEG;

inline void Int(int &x) {

    NEG = 0;

    while(!isdigit(IN=getchar()))

        if(IN=='-')NEG = 1;

    x = IN-'0';

    while(isdigit(IN=getchar()))

        x = x*10+IN-'0';

    if(NEG)x = -x;

}

inline void LL(ll &x) {

    NEG = 0;

    while(!isdigit(IN=getchar()))

        if(IN=='-')NEG = 1;

    x = IN-'0';

    while(isdigit(IN=getchar()))

        x = x*10+IN-'0';

    if(NEG)x = -x;

}



/******** program ********************/



const double eps=1e-8;

const double PI = acos(-1.0);



double dis(double a,double b){

    return a*a+b*b;

}



int dcmp(double x){

    if(fabs(x)<eps)return 0;

    return x>0?1:-1;

}





double ox,oy,r;

bool cc(double x1,double y1,double x2,double y2,double x3,double y3){

    ox = (x1+x2)/2,oy = (y1+y2)/2;

    r = dis(ox-x2,oy-y2);

    if( dcmp(dis(ox-x3,oy-y3)-r)<=0 )

        return true;

    return false;

}



void solve(){

    double x,y;

    cin>>x>>y;

    if(dcmp(dis(x-ox,y-oy)-r)>0)puts("Safe");

    else puts("Danger");

}



int main() {



#ifndef ONLINE_JUDGE

    freopen("sum.in","r",stdin);

    //freopen("sum.out","w",stdout);

#endif



    int Ncase = 0;

    int ncase;

    RD(ncase);

    double x1,x2,x3,y1,y2,y3;

    while(ncase--) {

        cin>>x1>>y1>>x2>>y2>>x3>>y3;



        printf("Case #%d: ",++Ncase);

        if(cc(x1,y1,x2,y2,x3,y3))

            solve();

        else if(cc(x2,y2,x3,y3,x1,y1))

            solve();

        else if(cc(x3,y3,x1,y1,x2,y2))

            solve();

        else{

            double k1=x2-x1,t1=y2-y1,k2=x3-x2,t2=y3-y2;

            double c1=(y2*y2+x2*x2-x1*x1-y1*y1)/2.0,c2=(y3*y3+x3*x3-x2*x2-y2*y2)/2.0;

            double a=(c1*t2-c2*t1)/(t2*k1-t1*k2),b=(c1*k2-c2*k1)/(t1*k2-k1*t2);

            double r=(a-x1)*(a-x1)+(b-y1)*(b-y1);

            cin>>x1>>y1;

            double d = dis(a-x1,b-y1);



            if(dcmp(d-r)>0)

                puts("Safe");

            else

                puts("Danger");

        }

    }



    return 0;

}

 

  

 

 

HDU 4721 Food and Productivity

待补

 

HDU 4722 Good Numbers

数位DP

 

#include <iostream>

#include <cstdio>

#include <cstring>

#include <cmath>

#include <algorithm>

#include <vector>

#include <map>

#include <stack>

#include <queue>



using namespace std;



#define pb push_back

#define mp make_pair

typedef long long ll;

ll f[20], a, b;

int num[20];

ll getnum(ll x) {

    if (x == -1) return 0;

    if (x == 0) return 1;

    int len = 0;

    int tmp = 0, t = 0;

    while(x) {

        tmp += x % 10;

        num[len++] = x % 10;

        x /= 10;

    }

    tmp -= num[0];

    ll ret = 0;

    for (int l = len-1; l >= 1; --l)

        ret += num[l]*f[l];

    for (int i = 0; i <= num[0]; ++i)

        if ((tmp+i) % 10 == 0) t = 1;

    return ret+t;

}

int main() {



#ifndef ONLINE_JUDGE

    freopen("sum.in","r",stdin);

    //freopen("sum.out","w",stdout);

#endif



    f[0] = 0;

    f[1] = 1;

    for (int i = 2; i <= 19; ++i) f[i] = f[i-1]*10;

    int T;

    scanf("%d", &T);

    for (int ncase = 1; ncase <= T; ++ncase) {

        scanf("%I64d%I64d", &a, &b);

        printf("Case #%d: %I64d\n",ncase,getnum(b)-getnum(a-1));

    }

    return 0;

}

 

  

 

 

HDU 4723 How Long Do You Have to Draw

怎么我感觉这题不难,难道我打开的方式不对?可惜比赛时没看题。。。

给出n个纵坐标为a的点,c1<c2<...<cn

给出m个纵坐标为b的点,d1<d2<...<dm

问如何对上下点进行连边,使得三角形最多,并且边不能相交。

分析:对于下图进行分析讨论即可。

如果c点已经到了最后,则:c点连剩下的d点

如果d点已经到了最后,则:d点连剩下的c点

如果c,d后面还有,有两种情况:

  1.为c1,d1,d2在c1,c2中线左边,则c1连d1,d后移

  2.为c1,d2,d3在c1,c2中线右边,则c1连d1,判断c1d3,c2d2的距离,根据那个更优移动哪个点即可。

2013 ACM/ICPC Asia Regional Online —— Warmup2

 

#include <set>

#include <map>

#include <list>

#include <cmath>

#include <queue>

#include <stack>

#include <string>

#include <vector>

#include <cstdio>

#include <cstring>

#include <iostream>

#include <algorithm>



using namespace std;



typedef long long ll;

typedef unsigned long long ull;



#define debug puts("here")

#define rep(i,n) for(int i=0;i<n;i++)

#define rep1(i,n) for(int i=1;i<=n;i++)

#define REP(i,a,b) for(int i=a;i<=b;i++)

#define foreach(i,vec) for(unsigned i=0;i<vec.size();i++)

#define pb push_back

#define RD(n) scanf("%d",&n)

#define RD2(x,y) scanf("%d%d",&x,&y)

#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)

#define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w)

#define All(vec) vec.begin(),vec.end()

#define MP make_pair

#define PII pair<int,int>

#define PQ priority_queue

#define cmax(x,y) x = max(x,y)

#define cmin(x,y) x = min(x,y)

#define Clear(x) memset(x,0,sizeof(x))

/*



#pragma comment(linker, "/STACK:1024000000,1024000000")



int size = 256 << 20; // 256MB

char *p = (char*)malloc(size) + size;

__asm__("movl %0, %%esp\n" :: "r"(p) );



*/



char IN;

bool NEG;

inline void Int(int &x){

    NEG = 0;

    while(!isdigit(IN=getchar()))

        if(IN=='-')NEG = 1;

    x = IN-'0';

    while(isdigit(IN=getchar()))

        x = x*10+IN-'0';

    if(NEG)x = -x;

}

inline void LL(ll &x){

    NEG = 0;

    while(!isdigit(IN=getchar()))

        if(IN=='-')NEG = 1;

    x = IN-'0';

    while(isdigit(IN=getchar()))

        x = x*10+IN-'0';

    if(NEG)x = -x;

}



/******** program ********************/



const int MAXN = 1e5+5;



double c[MAXN],d[MAXN],a,b;



double dis(double x,double y){

    return sqrt(x*x+y*y);

}

double dis(double x1,double y1,double x2,double y2){

    return dis(x1-x2,y1-y2);

}



int main(){



#ifndef ONLINE_JUDGE

    freopen("sum.in","r",stdin);

    //freopen("sum.out","w",stdout);

#endif



    int ncase,n,m,Ncase = 0;

    RD(ncase);

    while(ncase--){

        printf("Case #%d: ",++Ncase);

        scanf("%lf%lf",&a,&b);

        RD2(n,m);

        rep1(i,n)

            scanf("%lf",&c[i]);

        rep1(i,m)

            scanf("%lf",&d[i]);



        double ans = 0;

        int x = 1 ,y = 1;

        while(x<=n&&y<=m){

            if( x==n ){

                ans += dis(c[x],a,d[y],b);

                y ++;

            }else if( y==m ){

                ans += dis(c[x],a,d[y],b);

                x ++;

            }else{

                if(d[y+1]*2<=c[x]+c[x+1]){

                    ans += dis(c[x],a,d[y],b);

                    y ++;

                }else{

                    ans += dis(c[x],a,d[y],b);

                    double tmp = dis(c[x],a,d[y+1],b);

                    double ret = dis(c[x+1],a,d[y],b);

                    if(ret<tmp)

                        x ++;

                    else y++;

                }

            }

        }

        printf("%.2lf\n",ans);

    }



    return 0;

}

  

 

HDU 4724 If You Know This,You Must Have NO GF

待补

 

HDU 4725 The Shortest Path in Nya Graph

 使用堆维护dijkstra的算法,每次从堆中取出一个节点,如果该节点所在的层没被标记,更新相邻两层,标记上(因为每次都从堆中去最小值,因此当前层的最优值必定是第一次访问时所得,进而更新其他的层)。至于边的松弛,跟普通的dijkstra一样。详细看代码。

#include <set>

#include <map>

#include <list>

#include <cmath>

#include <queue>

#include <stack>

#include <string>

#include <vector>

#include <cstdio>

#include <cstring>

#include <iostream>

#include <algorithm>



using namespace std;



typedef long long ll;

typedef unsigned long long ull;



#define debug puts("here")

#define rep(i,n) for(int i=0;i<n;i++)

#define rep1(i,n) for(int i=1;i<=n;i++)

#define REP(i,a,b) for(int i=a;i<=b;i++)

#define foreach(i,vec) for(unsigned i=0;i<vec.size();i++)

#define pb push_back

#define RD(n) scanf("%d",&n)

#define RD2(x,y) scanf("%d%d",&x,&y)

#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)

#define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w)

#define All(vec) vec.begin(),vec.end()

#define MP make_pair

#define PII pair<int,int>

#define PQ priority_queue

#define cmax(x,y) x = max(x,y)

#define cmin(x,y) x = min(x,y)

#define Clear(x) memset(x,0,sizeof(x))

/*



#pragma comment(linker, "/STACK:1024000000,1024000000")



int size = 256 << 20; // 256MB

char *p = (char*)malloc(size) + size;

__asm__("movl %0, %%esp\n" :: "r"(p) );



*/



char IN;

bool NEG;

inline void Int(int &x){

    NEG = 0;

    while(!isdigit(IN=getchar()))

        if(IN=='-')NEG = 1;

    x = IN-'0';

    while(isdigit(IN=getchar()))

        x = x*10+IN-'0';

    if(NEG)x = -x;

}

inline void LL(ll &x){

    NEG = 0;

    while(!isdigit(IN=getchar()))

        if(IN=='-')NEG = 1;

    x = IN-'0';

    while(isdigit(IN=getchar()))

        x = x*10+IN-'0';

    if(NEG)x = -x;

}



/******** program ********************/



const int MAXN = 1e5+5;

const int INF = 1e9+7;



struct Edge{

    int y,cost,next;

}edge[MAXN<<1];



int po[MAXN],tol;

vector<int> vec[MAXN];

int la[MAXN],n,per,m;

int dis[MAXN];

bool use[MAXN];

bool ok[MAXN];



struct node{

    int x,cost;

    friend bool operator < (node a,node b){

        return a.cost>b.cost;

    }

    node(){}

    node(int _x,int _cost):x(_x),cost(_cost){}

};



int dijkstra(){

    priority_queue<node> q;

    Clear(use);

    rep1(i,n)dis[i] = INF;

    q.push(node(1,0));

    dis[1] = 0;

    Clear(ok);

    while(!q.empty()){

        node p = q.top();

        q.pop();

        int x = p.x;

        if(use[x])continue;

        use[x] = 1;

        if(x==n&&dis[n]<INF)break;



        if(!ok[la[x]]){

                ok[la[x]] = 1;

                int now = la[x]-1;

                if(now)

                    foreach(i,vec[now]){

                        int y = vec[now][i];

                        if(!use[y]&&dis[x]+per<dis[y]){

                            dis[y] = dis[x]+per;

                            q.push(node(y,dis[y]));

                        }

                    }

                now += 2;

                if(now<=n)

                    foreach(i,vec[now]){

                        int y = vec[now][i];

                        if(!use[y]&&dis[x]+per<dis[y]){

                            dis[y] = dis[x]+per;

                            q.push(node(y,dis[y]));

                        }

                    }

        }

        for(int i=po[x];i;i=edge[i].next){

            int y = edge[i].y;

            int tmp = edge[i].cost+dis[x];

            if(!use[y]&&tmp<dis[y]){

                dis[y] = tmp;

                q.push(node(y,dis[y]));

            }

        }

    }



    return dis[n];

}



inline void add(int x,int y,int cost){

    edge[++tol].y = y;

    edge[tol].cost = cost;

    edge[tol].next = po[x];

    po[x] = tol;

}



int main(){



#ifndef ONLINE_JUDGE

    freopen("cf.in","r",stdin);

    //freopen("sum.out","w",stdout);

#endif



    int x,y,c,ncase,Ncase = 0;

    RD(ncase);

    while(ncase--){

        printf("Case #%d: ",++Ncase);

        RD3(n,m,per);

        rep1(i,n)

            vec[i].clear();

        rep1(i,n){

            RD(la[i]);

            vec[la[i]].pb(i);

        }



        Clear(po);

        tol = 0;

        while(m--){

            RD3(x,y,c);

            add(x,y,c);

            add(y,x,c);

        }



        int ans = dijkstra();

        printf("%d\n",ans==INF?-1:ans);

    }



    return 0;

}

  

 

 

HDU 4726 Kia's Calculation

贪心。第一位想清楚了,后面的直接贪心。略

 

HDU 4727 The Number Off of FFF

水题。注意全对时输出1。略

 

 

 

你可能感兴趣的:(online)