2017-3-01 test

三道好像都是HDU上的题QAQ

题目名称都没改,差评

T1:http://acm.hdu.edu.cn/showproblem.php?pid=5073

   被卡精度了QAQ

   先排一发序,然后发现最后未动过的点一定是一段连续的区间,且其他点都被移动至其平均数处

   所以直接O(n)乱搞即可

   P.S.HDU上好像不能用long double

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int Mx=50010;
int n,k;
long double ans,tmp,sum,ave,a[Mx];
bool cmp(long double a,long double b) { return a<b; }
int main()  
{
    int T; scanf("%d",&T);
    for(int t=1;t<=T;t++)
    {
        printf("Case #%d:
",t);
        tmp=0,sum=0;
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++) scanf("%LF",&a[i]);
        if(n==k) { cout<<"0.000000"<<endl; continue; }
        sort(a+1,a+1+n,cmp);
        for(int i=1;i<=n-k;i++) tmp+=a[i]*a[i],sum+=a[i];ave=sum/(n-k);
        ans=tmp-2*ave*sum+(n-k)*ave*ave;
        for(int l=1,r=n-k+1;r<=n;l++,r++)
        {
            tmp+=a[r]*a[r]-a[l]*a[l];
            sum+=a[r]-a[l];
            ave=sum/(n-k);
            ans=min(ans,tmp-2*ave*sum+(n-k)*ave*ave);
        }
        printf("%.8LF
",ans);
    }
    return 0;
}

T2:http://acm.hdu.edu.cn/showproblem.php?pid=5833

   一言不合就数论QAQ

   首先先预处理2000以内的素数,然后将a[]质因数分解

   我们发现,一个完全平方数的各个质因子都是偶数次方,所以每次乘起来就等价于把系数^1

   所以可以构造转移矩阵,第i行j列表示第j个素数在a[i]中的系数%2

   高斯一发然后答案即为pow(2,自由元的个数)-1,记得开long long

   P.S.自由元:消完之后一行都是0

#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int Mx=2010;
const long long p=1e9+7;
int n,cnt,pr[Mx],vis[Mx],tran[310][310];
void pre()
{
    for(int i=2;i<=2000;i++)
    {
        int jud=1;
        for(int j=2;j*j<=i;j++)
            if(i%j==0) jud=0;
        if(jud) pr[++cnt]=i;
    }
}
long long power(long long a,long long b)
{
    long long c=1;
    while(b)
    {
        if(b&1) c=c*a%p;
        a=a*a%p;
        b>>=1;
    }
    return c;
}
int gauss()
{
    int i=1;
    for(int j=1;i<=cnt&&j<=n;i++,j++)
    {
        int tmp=i;
        for(int k=i+1;k<=cnt;k++)
            if(tran[k][j]>tran[tmp][j]) tmp=k;
        if(tmp!=i)
            for(int k=j;k<=n+1;k++) swap(tran[tmp][k],tran[i][k]);
        if(tran[i][j]==0) { i--; continue; }
        for(int k=i+1;k<=cnt;k++)
        {
            if(!tran[k][j]) continue;
            for(int l=j;l<=n+1;l++)
                tran[k][l]=tran[k][l]^tran[i][l];
        }
    }
    return n-(i-1);
}
int main()
{
    pre();
    int T; scanf("%d",&T);
    for(int t=1;t<=T;t++)
    {
        memset(tran,0,sizeof(tran));
        printf("Case #%d:
",t);
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            long long x; scanf("%lld",&x);
            for(int j=1;j<=cnt;j++)
            {
                int tot=0;
                while(x%pr[j]==0)
                    x/=pr[j],tot++;
                tran[j][i]=tot&1;
            }
        }
        printf("%lld
",(long long) power(2,gauss())-1);
    }
    return 0;
}

 T3:http://acm.hdu.edu.cn/showproblem.php?pid=5770

   好麻烦啊QAQ调了半天调不出来只能把std放上去了QAQ

   orz ZSQ:http://blog.csdn.net/v5zsq/article/details/52170616

   对于一组钥匙和宝箱u,v及其lca,我们可以分类讨论,有以下四种情况

   1、u!=lca&&v!=lca:要想拿到宝箱,起点必须在u的子树中,终点必须在v的子树中

   2、u==lca:起点不能在u的子树中,终点必须在v的子树中

   3、v==lca:起点不能在v的子树中,终点必须在v的子树中

   4、u==v:起点和终点在lca的不同子树中 或 起点or终点在lca的子树中,另一个点不在lca的子树中

    这种情况为保证复杂度所以要反过来求不包含该节点的路径

    ①起点和终点都在lca的同一个儿子中

    ②起点和终点都不在在lca的子树中,即起点和终点x的dfs序都满足(x<l || x>r)

   考虑维护DFS序,将以i为根的子树处理成一个区间[l,r],则每个宝箱可以映射为一个带权矩阵,对应上述情况

   建立一个二维平面,平面上的点(x,y)表示从x走到y的价值,点权即为包含该点的所有矩阵的和

   最后用扫描线+线段树即可解决

   默默吐槽一下,std代码好吃藕啊QAQ(逃~

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;

const int N = 200010;
int to[N << 1], nxt[N << 1], head[N], cnt;
void add(int x, int y){
    to[++ cnt] = y; nxt[cnt] = head[x]; head[x] = cnt;
    to[++ cnt] = x; nxt[cnt] = head[y]; head[y] = cnt;
}

struct Rec{
    int x1, x2, y1, y2, val;
}rec[N * 10];
struct Event{
    int l, r, y, val, rank;
}events[N * 10];
bool operator < (const Event &a, const Event &b){
    return a.y < b.y || (a.y == b.y && a.rank < b.rank);
}

struct treasure{
    int key, chest, val;
}a[N];
int st[N], ed[N], n, m, dfs_clock, dep[N], fa[N][20];

int LCA(int x, int y){
    if (dep[x] < dep[y]) swap(x, y);
    int t = dep[x] - dep[y];
    for(int i = 0; i < 20; i ++) if (t >> i & 1) x = fa[x][i];
    for(int i = 19; i >= 0; i --)
        if (fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];
    if (x == y) return x;
    return fa[x][0];
}

void dfs(int x){
    st[x] = ++ dfs_clock;
    for(int i = 1; (1 << i) <= dep[x]; i ++)
        fa[x][i] = fa[fa[x][i - 1]][i - 1];
    for(int i = head[x]; i; i = nxt[i])
        if (st[to[i]] == 0){
            dep[to[i]] = dep[x] + 1;
            fa[to[i]][0] = x;
            dfs(to[i]);
        }
    ed[x] = dfs_clock;
}

struct node{
    int tag, max;
}t[N << 2];
#define mid ((l + r) >> 1)
#define L (o << 1)
#define R (o << 1 | 1)
#define lch L, l, mid
#define rch R, mid + 1, r

void Push_up(int o){
    t[o].max = max(t[L].max, t[R].max);
}
void change(int o, int v){
    t[o].tag += v; t[o].max += v;
}
void Push_down(int o){
    if (t[o].tag){
        change(L, t[o].tag);
        change(R, t[o].tag);
        t[o].tag = 0;
    }
}
void update(int o, int l, int r, int ql, int qr, int v){
    if (ql > qr) return;
    if (ql <= l && qr >= r) change(o, v);
    else{
        Push_down(o);
        if (ql <= mid) update(lch, ql, qr, v);
        if (qr >  mid) update(rch, ql, qr, v);
        Push_up(o);
    }
}

int main(){
    int T, cs = 0;
    scanf("%d", &T);
    while(cs < T){
        printf("Case #%d: ", ++ cs);

        memset(head, 0, sizeof head);
        memset(st, 0, sizeof st);
        memset(fa, 0, sizeof fa);
        memset(dep, 0, sizeof dep);
        memset(t, 0, sizeof t);
        cnt = dfs_clock = 0;
        scanf("%d%d", &n, &m);
        int x, y;
        for(int i = 1; i < n; i ++){
            scanf("%d%d", &x, &y);
            add(x, y);
        }
        dfs(1);
//        for(int i = 1; i <= n; i ++) printf("st[%d] = %d ed[%d] = %d
", i, st[i], i, ed[i]);
        int tot = 0, num = 0, ans = 0, tmp = 0;
        for(int i = 1; i <= m; i ++){
            scanf("%d%d%d", &a[i].key, &a[i].chest, &a[i].val);
            int lca = LCA(a[i].key, a[i].chest);
            if (a[i].key == a[i].chest){
                tmp += a[i].val;
                for(int j = head[a[i].key]; j; j = nxt[j])
                    if (to[j] != fa[a[i].key][0]){
                        rec[++ tot] = (Rec){st[to[j]], ed[to[j]], st[to[j]], ed[to[j]], -a[i].val};
                    }
                if (1 <= st[a[i].key] - 1 && ed[a[i].key] + 1 <= n){
                    rec[++ tot] = (Rec){1, st[a[i].key] - 1, ed[a[i].key] + 1, n, -a[i].val};
                    rec[++ tot] = (Rec){ed[a[i].key] + 1, n, 1, st[a[i].key] - 1, -a[i].val};
                }
                if (1 <= st[a[i].key] - 1)
                    rec[++ tot] = (Rec){1, st[a[i].key] - 1, 1, st[a[i].key] - 1, -a[i].val};
                if (ed[a[i].key] + 1 <= n)
                    rec[++ tot] = (Rec){ed[a[i].key] + 1, n, ed[a[i].key] + 1, n, -a[i].val};
            }else if (a[i].key == lca){
                for(int j = head[a[i].key]; j; j = nxt[j])
                    if (to[j] != fa[a[i].key][0] && LCA(to[j], a[i].chest) == to[j]){
                        y = to[j];
                        break;
                    }
                if (1 <= st[y] - 1) rec[++ tot] = (Rec){1, st[y] - 1, st[a[i].chest], ed[a[i].chest], a[i].val};
                if (ed[y] + 1 <= n) rec[++ tot] = (Rec){ed[y] + 1, n, st[a[i].chest], ed[a[i].chest], a[i].val};
            }else if (a[i].chest == lca){
                for(int j = head[a[i].chest]; j; j = nxt[j])
                    if (to[j] != fa[a[i].chest][0] && LCA(to[j], a[i].key) == to[j]){
                        y = to[j];
                        break;
                    }
                if (1 <= st[y] - 1) rec[++ tot] = (Rec){st[a[i].key], ed[a[i].key], 1, st[y] - 1, a[i].val};
                if (ed[y] + 1 <= n) rec[++ tot] = (Rec){st[a[i].key], ed[a[i].key], ed[y] + 1, n, a[i].val};
            }else{
                rec[++ tot] = (Rec){st[a[i].key], ed[a[i].key], st[a[i].chest], ed[a[i].chest], a[i].val};
            }
//            if (rec[tot].x1 == 0) printf("%d %d %d lca = %d
", a[i].key, a[i].chest, a[i].val, lca);
        }
//        for(int i = 1; i <= tot; i ++)
//            printf("%d %d %d %d %d
", rec[i].x1, rec[i].x2, rec[i].y1, rec[i].y2, rec[i].val);
        int tt = 0;
        for(int i = 1; i <= tot; i ++){
//            if (rec[i].x1 == 0 && rec[i].x2 == 0) printf("%d
", ++ tt);
            events[++ num] = (Event){rec[i].x1, rec[i].x2, rec[i].y1, rec[i].val, 1};
            events[++ num] = (Event){rec[i].x1, rec[i].x2, rec[i].y2 + 1, -rec[i].val, 0};
        }
        sort(events + 1, events + num + 1);
        for(int i = 1; i <= num; i ++){
            if (events[i].y > events[i - 1].y || i == 1) ans = max(ans, t[1].max);
            update(1, 1, n, events[i].l, events[i].r, events[i].val);
            if (i == num) ans = max(ans, t[1].max);
//            printf("%d
", t[1].max);
        }
        printf("%d
", ans + tmp);
    }
    return 0;
}

   

原文地址:https://www.cnblogs.com/xiaoxubi/p/6484441.html