2017-4-7校内训练

丧病hzwer的ctsc训练赛 My AC:3/4

A.[Ctsc2014]企鹅QQ

思路:乱hash,我比较菜,写的丑代码各种WA+TLE,好久才A掉。

#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
#define MN 200
#define MX 6000000
#define MM 9000001
#define MOD1 890123798112473LL
struct map
{
    struct edge{int nx,t;ll x;}e[MX+5];
    int h[MM],en;
    inline int&operator[](ll x)
    {
        int p=(x%MM+MM)%MM;
        for(int i=h[p];i;i=e[i].nx)if(e[i].x==x)return e[i].t;
        e[++en]=(edge){h[p],0,x};h[p]=en;
        return e[en].t;
    }
}mp1,mp2;
char s[MN+5];
ll f1[MN+5],f2[MN+5];
int main()
{
    int n,m,k,i,ans=0;ll h1,h2;
    scanf("%d%d%d",&n,&m,&k);
    while(n--)
    {
        scanf("%s",s+1);
        for(i=m;i;--i)f1[i]=(f1[i+1]*31^(s[i]+23))%MOD1,
                      f2[i]=(f2[i+1]*37^(s[i]+23));
        for(i=1,h1=h2=0;i<=m;++i)
        {
            ans+=min(mp1[h1*23333^f1[i+1]]++,mp2[h2*23333^f2[i+1]]++);
            h1=(h1*37+s[i])%MOD1;h2=(h2*31+s[i]);
        }
    }
    printf("%d",ans);
}

B.[CTSC2007]数据备份Backup

思路:显然只有相邻的会被选,先把所有相邻线段用链表链起来塞到堆里,每次取出最小的,与他相邻的线段暂时不能选就删掉,如果要在之后再选相邻的这两条,显然不可能只选其中一条而不选中间这条,我们把这三条合并成左+右-中再塞回堆即可。

#include<cstdio>
#include<queue>
using namespace std;
inline int read()
{
    int x;char c;
    while((c=getchar())<‘0‘||c>‘9‘);
    for(x=c-‘0‘;(c=getchar())>=‘0‘&&c<=‘9‘;)x=(x<<3)+(x<<1)+c-‘0‘;
    return x;
}
#define MN 100000
int a[MN+5],l[MN+5],r[MN+5],w[MN+5],u[MN+5];
class cmp{public:bool operator()(int a,int b){return w[a]>w[b];}};
priority_queue<int,vector<int>,cmp> pq;
int main()
{
    int n,k,i,x,ans=0;
    n=read();k=read();
    for(i=1;i<=n;++i)a[i]=read();
    w[0]=w[n]=1e9;
    for(i=1;i<n;++i)l[i]=i-1,r[i]=i+1,w[i]=a[i+1]-a[i],pq.push(i);
    for(i=0;i<k;++i)
    {
        do x=pq.top(),pq.pop();while(u[x]);
        ans+=w[x];
        w[x]=w[l[x]]+w[r[x]]-w[x];
        u[l[x]]=u[r[x]]=1;
        l[x]=l[l[x]];r[x]=r[r[x]];
        pq.push(r[l[x]]=l[r[x]]=x);
    }
    printf("%d",ans);
}

C.[Ctsc2015]misc

思路:枚举s,每个s先跑一遍单源最短路,只考虑最短路上的边(即满足dis[u]+len=dis[v]的边),得到一张拓扑图,在拓扑图上先dp出s到每个点的最短路宽度$\sigma_{st}$;

考虑每个v,$R(v)=\sum \frac{a_{s}a_{t}\sigma_{st}(v)}{\sigma{st}}=\sum \frac{a_{s}a_{t}\sigma_{sv}\sigma_{vt}}{\sigma{st}}=a_{s}\sigma_{sv}\sum\frac{a_{t}\sigma_{vt}}{\sigma_{st}}$,其中t为v在最短路拓扑图中能到的点。

我们令$f(v)=\sum\frac{a_{t}\sigma_{vt}}{\sigma_{st}}$,则有$f(u)=\sum c_{j}(\frac{a_{v}}{\sigma_{sv}}+f(v))$,其中j为u到v的一条最短路边。然后DP下就做完了。

#include<cstdio>
#include<cstring>
#define MN 1000
#define MM 4000
#define N 1024
#define lb long double
struct edge{int nx,t,w;lb c;}e[MM*2+5];
int n,h[MN+5],en,a[MN+5],d[MN+5],q[MN+5],qn,r[MN+5];
lb fk[MN+5],fj[MN+5],ans[MN+5];
inline void ins(int x,int y,int w,lb c)
{
    e[++en]=(edge){h[x],y,w,c};h[x]=en;
    e[++en]=(edge){h[y],x,w,c};h[y]=en;
}
struct data{int x,f;}t[N*2+5];
data min(data a,data b){return a.x<b.x?a:b;}
void change(int k,int x){for(t[k+=N].x=x;k>>=1;)t[k]=min(t[k<<1],t[k<<1|1]);}
void dj(int s)
{
    memset(d,127,sizeof(d));
    memset(t,127,sizeof(t));
    for(int i=1;i<=n;++i)t[i+N].f=i;
    for(change(s,d[s]=0);t[1].x<d[0];change(t[1].f,d[0]))
        for(int i=h[t[1].f];i;i=e[i].nx)if(d[t[1].f]+e[i].w<d[e[i].t])
            change(e[i].t,d[e[i].t]=d[t[1].f]+e[i].w);
}
void pre()
{
    int i,j;
    memset(r,0,sizeof(r));
    for(i=1;i<=n;++i)for(j=h[i];j;j=e[j].nx)
        if(d[i]+e[j].w==d[e[j].t])++r[e[j].t];
    for(i=1,qn=0;i<=n;++i)if(!r[i])q[++qn]=i;
    for(i=1;i<=qn;++i)
    {
        fk[q[i]]=i<2;
        for(j=h[q[i]];j;j=e[j].nx)
        {
            if(d[e[j].t]+e[j].w==d[q[i]])fk[q[i]]+=fk[e[j].t]*e[j].c;
            if(d[q[i]]+e[j].w==d[e[j].t]&&!--r[e[j].t])q[++qn]=e[j].t;
        }
    }
}
void solve(int s)
{
    int i,j;
    memset(r,0,sizeof(r));
    for(i=1;i<=n;++i)for(j=h[i];j;j=e[j].nx)
        if(d[i]+e[j].w==d[e[j].t])++r[i];
    for(i=1,qn=0;i<=n;++i)if(!r[i])q[++qn]=i;
    for(i=1;i<=qn;++i)
    {
        fj[q[i]]=0;
        for(j=h[q[i]];j;j=e[j].nx)
        {
            if(d[q[i]]+e[j].w==d[e[j].t])fj[q[i]]+=fj[e[j].t]*e[j].c;
            if(d[e[j].t]+e[j].w==d[q[i]]&&!--r[e[j].t])q[++qn]=e[j].t;
        }
        if(q[i]!=s)ans[q[i]]+=a[s]*fk[q[i]]*fj[q[i]];
        fj[q[i]]+=a[q[i]]/fk[q[i]];
    }
}
int main()
{
    int m,i,j,x,y,w;double c;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;++i)scanf("%d",&a[i]);
    while(m--)scanf("%d%d%d%lf",&x,&y,&w,&c),ins(x,y,w,c);
    for(i=1;i<=n;++i)dj(i),pre(),solve(i);
    for(i=1;i<=n;++i)printf("%.7lf\n",(double)ans[i]);
}
时间: 2024-10-22 14:26:47

2017-4-7校内训练的相关文章

2017.09.03校内训练

T1:卡片 题解:这很明显,是一道选择题!!! 我们考虑每一种情况:只有一种卡片时,很显然最后剩下的只能是这一种:有三种卡片时,可以变成各只有一张,无论选取哪两张,都可以变成剩下的那一张,因此每一种都可以剩下:有两种的情况:若这两种都有两张以上,便可以各取一张合成没有的那一种,最后结果请参见上一条:若有一种只有一张,另一种有多张,则每一次的转化操作都要使用到较多的那种一张,不论如何都不可能合成较多张的那一种.因此结果是除了多于一张的那一种以外的其它两种:若这两种各只有一张,则结果必定是没有的那一

2017.09.24校内训练

T1:个人卫生综合征 题目描述: 每天BBS都要从家里经过城市中的一段路到学校刷五三.城市中一共有n个路口和m条双向道路,每条双向道路都连接着两个路口ai.bi且有一定的时间花费vi.BBS家编号为1,学校编号为n.今天,BBS由于个人卫生综合征导致他很迟才离开家,他想用膜法改变k条道路的长度使通过其的时间花费vi变为0.现在他问你改变道路长度之后他到学校的最小时间花费是多少? 输入格式: 第一行为三个整数n.m.k,接下来的m行每行三个整数ai,bi,vi,分别表示这条路连着的两个路口和通过其

2017.6.11 校内模拟赛

题面及数据及std(有本人的也有原来的) :2017.6.11 校内模拟赛 T1 自己在纸上模拟一下后就会发现 可以用栈来搞一搞事情 受了上次zsq 讲的双栈排序的启发.. 具体就是将原盘子大小copy一下排个序 用两个指针维护两个数组(原数据 和 排序后的数据), 即分为1数据和2数组 将小于1指针指向的数据的2数组中的数据全部压入栈中 后进行消除, 将栈栈顶元素与当前1数组中的1指针指向的元素进行比较 相同则消除 后重复过程 直至指针超过N 后判断一下是否两个指针都超过了N... #incl

「csp校内训练 2019-10-24」解题报告

「csp校内训练 2019-10-24」解题报告 T1.猴猴吃苹果 \(Description\) 猴猴最喜欢在树上玩耍,一天猴猴又跳上了一棵树,这棵树有 \(N \ (N \leq 50000)\) 个苹果,每个苹果有一个编号,分别为 \(0\) ~ \(N - 1\) 它们之间由 \(N-1\) 个树枝相连,猴猴可以从树枝的一端爬到树枝的另一端,所以猴猴可以从任意一个苹果的位置出发爬到任意猴猴想去的苹果的位置. 猴猴开始在编号为 \(K \ (K < N)\) 的苹果的位置,并且把这个苹果吃

「csp校内训练 2019-10-30」解题报告

「csp校内训练 2019-10-30」解题报告 T1.树 题目链接(逃) \(Description\): 现在有一棵树,共 \(N\) 个节点. 规定:根节点为 \(1\) 号节点,且每个节点有一个点权. 现在,有 \(M\) 个操作需要在树上完成,每次操作为下列三种之一: \(1 \ x \ a\):操作 \(1\),将节点 \(x\) 点权增加 \(a\). \(2 \ x \ a\):操作 \(2\),将以节点 \(x\) 为根的子树中所有点的权值增加 \(a\). \(3 \ x\)

20170910校内训练

CCT 最近学校又发了n本五三题霸,BBS看到后十分高兴.但是,当他把五三拿到手后才发现,他已经刷过这些书了!他又认真地看了一会儿,发现新发的这些五三是2017版的,而他刷的是2016版的.现在他想找出所有他没有刷过的题来刷.每本五三都有m道题,并且它的特征(即它和去年版本的五三的差距)可以用一个m位二进制数来代表,二进制位上的1代表该题不同,0代表该题相同.比如4(100)就代表题目3和去年的有不同.5(101)就代表题目1和题目3和去年的有不同.而BBS热衷于给自己找麻烦,他要选择连续一段的

2017.9.17校内noip模拟赛解题报告

预计分数:100+60+60=220 实际分数:100+60+40=200 除了暴力什么都不会的我..... T1 2017.9.17巧克力棒(chocolate) 巧克力棒(chocolate)Time Limit:1000ms Memory Limit:64MB题目描述LYK 找到了一根巧克力棒,但是这根巧克力棒太长了,LYK 无法一口吞进去.具体地,这根巧克力棒长为 n,它想将这根巧克力棒折成 n 段长为 1 的巧克力棒,然后慢慢享用.它打算每次将一根长为 k 的巧克力棒折成两段长为 a

2017-3-3校内训练

hzwer出丧题虐人啦 ACM赛制 4/7 A.恼人的青蛙 题目大意:给定N*M矩阵上K个点,定义一条合法路径为从矩形外一点沿一条直线穿过矩形,每次走相同长度且在矩形内每步都要踩在给定点上,问经过给定点最多的路径经过几个点(若小于3输出0)(N,M,K<=5000). 思路:把点按横坐标第一关键字纵坐标第二关键字排序,f[i][j]表示有一条到i的路径,i上一个点是j,此时路径经过点数,每次确定i,j后就可以根据i,j算出j再前一个点的坐标,直接转移,复杂度O(K^2).评测机极慢稍微卡卡常才能

【三中校内训练】旅行

[题解] 显然的这是一道树形DP的题目 这里令f[i][0]为从i出发向以它为根的子树里走直到不能走的最大.最小价值 (不能走是什么自己阅读题目) 令s为x的儿子,w[i][j]为i和j之间的边的长度,则 f[x][0]=max(f[s][1]+w[s][i]) f[x][1]=min(f[s][0]+w[s][i]) 显然的通过这种方法,我们可以得到60分 可是,如何优化到线性呢 我们考虑一个节点x,x向某条边走的情况出现了很多次,浪费了很多时间 我们定义h[x][0/1]为从x出发,经过x的