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的距离,根据那个更优移动哪个点即可。

 

#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。略

 

 

 

posted @ 2013-09-12 14:46  yejinru  阅读(403)  评论(0编辑  收藏  举报