【NOIP2016TG】solution

传送门:https://www.luogu.org/problem/lists?name=&orderitem=pid&tag=83%7C33

D1T1(toys)

题意:有n个小人,给你M条指令,每条指令可顺可逆(时针),问你操作后的位置在哪。

解题思路:裸模拟即可。

#include<stdio.h>
using namespace std;
#define MN 100005
char a[MN][15];
int n,m;
bool b[MN];
inline int in(){
    int x=0;char ch=getchar();
    while(ch<‘0‘||ch>‘9‘) ch=getchar();
    while(ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();
    return x;
}
int main(){
    n=in();m=in();
    for (int i=1; i<n; ++i){b[i]=in();scanf("%s",a[i]);}
    b[0]=in();scanf("%s",a[0]);
    int nt=1;
    for(int i=1; i<=m; ++i){
        int x=(in()^b[nt])?1:-1,k=in();nt+=k*x;
        if (nt<0) nt+=2*n;nt%=n;
    }
    puts(a[nt]);
}

D1T2(running)

大丧题,解题思路已经存在博客中了,这里放一下传送门,顺便贴个代码。

传送门:http://www.cnblogs.com/Melacau/p/NOIP2016_running.html

贴代码:

#include<stdio.h>
#define MN 300005
#define nt edge[i].to
struct zxy{int to,next;}edge[MN*8];//链表(把多个链表都塞进去了)
int cnt,h[MN],q[MN],adh1[MN],deh1[MN],adh2[MN],deh2[MN];//各链表表头
int qans[MN],tim[MN],deep[MN],n,m,chafen[MN*3],fa[MN],ans[MN],x[MN],y[MN];
bool vis[MN];
inline void ins(int *h,int x,int y){edge[++cnt].next=h[x],edge[cnt].to=y,h[x]=cnt;}//构造链表
inline int getfa(int x){return fa[x]?fa[x]=getfa(fa[x]):x;}//并查集
inline int in(){
    int x=0,f=1;char ch=getchar();
    while(ch<‘0‘||ch>‘9‘) f=ch==‘-‘?-1:1,ch=getchar();
    while(ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();
    return x*f;
}
inline void tjlca(int x,int d){
    deep[x]=d;vis[x]=1;
    for (register int i=h[x]; i; i=edge[i].next)
        if (!vis[nt])tjlca(nt,d+1),fa[nt]=x;
    for (register int i=q[x]; i; i=edge[i].next)
        if (qans[nt]) qans[nt]=getfa(qans[nt]);
        else qans[nt]=x;
}//tarjan算法求LCA
inline void dfs1(int u){
    vis[u]=0;ans[u]-=chafen[deep[u]-tim[u]];
    for (register int i=h[u]; i; i=edge[i].next) if (vis[nt]) dfs1(nt);
    for (register int i=adh1[u]; i; i=edge[i].next) ++chafen[nt];
    ans[u]+=chafen[deep[u]-tim[u]];
    for (register int i=deh1[u]; i; i=edge[i].next) --chafen[nt];
}//dfs处理S->f的
inline void dfs2(int u){
    vis[u]=1;ans[u]-=chafen[deep[u]+tim[u]];
    for (register int i=h[u]; i; i=edge[i].next) if (!vis[nt]) dfs2(nt);
    for (register int i=adh2[u]; i; i=edge[i].next) ++chafen[nt];
    ans[u]+=chafen[deep[u]+tim[u]];
    for (register int i=deh2[u]; i; i=edge[i].next) --chafen[nt];
}//dfs处理f->T的
void read(){
    n=in(),m=in();int u,v;
    for (int i=1; i<n; ++i) u=in(),v=in(),ins(h,u,v),ins(h,v,u);
    for (register int i=1; i<=n; ++i) tim[i]=in()-MN;//为了防止减法出现负数,所以我们要这么做。
    for (register int i=1; i<=m; ++i) x[i]=in(),y[i]=in(),ins(q,x[i],i),ins(q,y[i],i);
}//输入
void init(){
    tjlca(1,0);
    for (register int i=1; i<=m; ++i){
        int f=qans[i],u=x[i],v=y[i];
        if (f==v) ins(adh2,u,deep[u]+MN),ins(deh2,v,deep[u]+MN);
        else{
            if (f==u) ins(adh1,v,deep[u]+MN),ins(deh1,u,deep[u]+MN);
            else{
                ins(adh2,u,deep[u]+MN);
                ins(deh2,f,deep[u]+MN);
                ins(adh1,v,(deep[f]<<1)-deep[u]+MN);
                ins(deh1,f,(deep[f]<<1)-deep[u]+MN);
                if(deep[f]==deep[u]-tim[f]-MN) --ans[f];
            }
        }
    }
}//处理差分位置
void solve(){
    dfs1(1);//进行第一次遍历统计答案
    for (register int i=1; i<=n; ++i) tim[i]+=MN<<1;//这个处理很关键!
    dfs2(1);
    for (register int i=1; i<n; ++i) printf("%d ",ans[i]); printf("%d",ans[n]);
}
int main(){
    read();
    init();
    solve();
}

D1T3(classroom)

题意:给你V个点,你一共要执行N个阶段,每个阶段可能在任意2个点上进行,不同点的概率不同,求执行完所有阶段的期望。

解题思路:floyd预处理最短路,然后跑期望DP。(注意精度控制)

#include <stdio.h>
#include <string.h>
#define min(a,b) (a<b?a:b)
#define inf 1e9
#define MN 2001
#define MV 301
using namespace std;
int n,m,v,e,cnt,dis[MV][MV],c[MN],d[MN];
double qw[MN],ans=inf,f[MN][MN][2];
inline int in(){
    int x=0,f=1;char c=getchar();
    while(c<‘0‘||c>‘9‘) f=c==‘-‘?-1:1,c=getchar();
    while(c>=‘0‘&&c<=‘9‘) x=x*10+c-‘0‘,c=getchar();
    return x*f;
}
void init(){
    n=in(),m=in(),v=in(),e=in();
    for (int i=1; i<=n; ++i) c[i]=in();
    for (register int i=1; i<=n; ++i) d[i]=in();
    for (register int i=1; i<=n; ++i) scanf("%lf",&qw[i]);
    for(register int i=1; i<=v; ++i)
        for(int j=1; j<=v; ++j){
            dis[i][j]=inf;
            if(!(i^j))dis[i][j]=0;
        }
    for (register int i=1; i<=e; ++i){register int x=in(),y=in(),c=in();dis[x][y]=dis[y][x]=min(dis[x][y],c);}
}
void floyd(){
    for (int k=1; k<=v; ++k)
        for (register int i=1; i<=v; ++i)
            for (int j=1; j<=v; ++j)
                if (i^j&&i^k&&j^k)
                    if(dis[i][j]>dis[i][k]+dis[k][j])
                        dis[i][j]=dis[i][k]+dis[k][j];
}
void dp(){
    if (n==1) {puts("0.00");return;}
    for (register int i=0; i<=m; ++i) f[1][i][0]=f[1][i][1]=0;
    for (register int i=2; i<=n; ++i)
        for (register int j=0; j<=min(i,m); ++j){
            f[i][j][0]=f[i][j][1]=inf;
            if(i^j){
                if((i-1)^j) f[i][j][0]=min(f[i][j][0],f[i-1][j][0]+dis[c[i-1]][c[i]]);
                if(j) f[i][j][0]=min(f[i][j][0],f[i-1][j][1]+qw[i-1]*dis[d[i-1]][c[i]]+(1-qw[i-1])*dis[c[i-1]][c[i]]);
                if (!(i^n)) ans=min(ans,f[i][j][0]);
            }
            if(j){
                if(j>1) f[i][j][1]=f[i-1][j-1][1]+qw[i-1]*qw[i]*dis[d[i-1]][d[i]]+qw[i-1]*(1-qw[i])*dis[d[i-1]][c[i]]+(1-qw[i-1])*qw[i]*dis[c[i-1]][d[i]]+(1-qw[i-1])*(1-qw[i])*dis[c[i-1]][c[i]];
                if(i^j) f[i][j][1]=min(f[i][j][1],f[i-1][j-1][0]+qw[i]*dis[c[i-1]][d[i]]+(1-qw[i])*dis[c[i-1]][c[i]]);
                if (!(i^n)) ans=min(ans,f[i][j][1]);
            }
        }
    printf("%.2lf",ans);
}
int main(){init();floyd();dp();return 0;}

D2T1(problem)

题意:自己看题目。

解题思路:杨辉三角形递推预处理即可,注意对k取余。

#include<stdio.h>
#define max(a,b) (a>b?a:b)
int t,k,n[10001],m[10001],mn,f[2005000],ans[2005000];
inline int in(){
    int x=0,f=1; char c=getchar();
    while(c<‘0‘||c>‘9‘) f=c==‘-‘?-1:1,c=getchar();
    while(c>=‘0‘&&c<=‘9‘) x=x*10+c-48,c=getchar();
    return x*f;
}
inline int doit(int n,int m){return n*(n+1)/2+m;}
void init(){
    t=in(),k=in();
    for (register int i=1; i<=t; ++i){n[i]=in();m[i]=in();mn=max(n[i],mn);}
    for (register int i=0; i<=mn; ++i) f[doit(i,0)]=1;
    for (register int i=1; i<=mn; ++i)
        for (register int j=1; j<=i; ++j)
            if(i^j){
                ans[doit(i,j)]=ans[doit(i-1,j)]+ans[doit(i,j-1)]-ans[doit(i-1,j-1)];
                f[doit(i,j)]=(f[doit(i-1,j-1)]+f[doit(i-1,j)])%k;
                if (!(f[doit(i,j)]%k)) ans[doit(i,j)]++;
            }
            else{
                ans[doit(i,j)]=ans[doit(i,j-1)];
                f[doit(i,j)]=f[doit(i-1,j-1)];
                if (!(f[doit(i,j)]%k)) ans[doit(i,j)]++;
            }
}
void solve(){
    for (register int i=1; i<=t; ++i)
        if (n[i]<m[i]) printf("%d\n",ans[doit(n[i],n[i])]);
        else printf("%d\n",ans[doit(n[i],m[i])]);
}
int main(){init();solve();return 0;}

D2T2(earthworm)

题意:就是你每次会选一堆东西中最长的出来,然后切成2部分再扔回去,叫你模拟出这个过程。

解题思路:正常的想法是扔个堆,然后按题意搞,时间会T(O((n+m)log(n+m)))。容易发现切出来的东西其实是有单调性的= =,然后就可以用3个队列(1个初始队列,2个切出来的队列)愉快的优化了,时间效率是O(nlogn+m).

/*代码在luogu上T了1个点。。。估计评测机太慢= =,BZOJ上过了,就假装没问题吧。*/

#include <stdio.h>
#include <algorithm>
#include <math.h>
#include <iostream>
#define MN 100005
#define MM 7000005
#define ll long long
#define inf 0x7fffffffffffffffLL
#define max(a,b) (a>b?a:b)
using namespace std;
int h[3],t[3],m,tt,dl;
ll que[3][MN+MM],q,u,v;
inline int in(){
    int x=0,f=1; char ch=getchar();
    while (ch<‘0‘||ch>‘9‘) f=ch==‘-‘?-1:1,ch=getchar();
    while (ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();
    return x*f;
}
inline ll get_top(){
    ll ma=-inf;dl=-1;
    for (register int i=0; i<3; ++i)
        if (h[i]<=t[i]&&que[i][h[i]]>ma) ma=que[i][h[i]],dl=i;
    if (dl!=-1) ++h[dl];return ma;
}
void init(){
    t[0]=in(),m=in(),q=in(),u=in(),v=in(),tt=in();
    for (int i=1; i<=t[0]; ++i) que[0][i]=in();
    sort(que[0]+1,que[0]+1+t[0],greater<int>());
    h[0]=h[1]=h[2]=1;
}
void solve(){
    for (register int i=1; i<=m; ++i){
        ll w=get_top()+(i-1)*q;
        if (i%tt==0) if (i/tt==1) printf("%lld",w);
                    else printf("% lld",w);
        que[1][++t[1]]=w*u/v-i*q;
        que[2][++t[2]]=w-(w*u/v)-i*q;
    }putchar(‘\n‘);
    for (register int i=1; ; ++i){
        ll w=get_top()+m*q;
        if (dl==-1) break;
        if (i%tt==0) if (i/tt==1) printf("%lld",w);else printf("% lld",w);
    }
}
int main(){init();solve();return 0;}
时间: 2024-08-06 20:03:48

【NOIP2016TG】solution的相关文章

about家庭智能设备部分硬件模块功能共享【协同工作】solution

本人设备列表: Onda tablet {Android} wifi Desktop computer {win7.centos7} 外接蓝牙adapter PS interface 键盘.鼠标{与同局域网laptop通过synergy软件共享,使其成为共享的输入设备} 3.5mm interface低音炮{通过Bluetooth连接laptop,从而让laptop也可以使用该声音输出设备} 250G硬盘,通过在linuxcentos上搭建NFSNetwork File System,使其硬盘资

【NOIP2013TG】solution

D1T1:转圈游戏(circle) 题意:看题目.. 解题思路:快速幂求m*10^kmodn即可. #include<stdio.h> #define ll long long #define For(i,a,b) for(int i=a; i<=b; i++) #define Ford(i,a,b) for(int i=a; i>=b; i--) #define File(fn) freopen(fn".in","r",stdin);fre

【NOIP2011TG】solution

老师最近叫我把NOIPTG的题目给刷掉,于是就开始刷吧= = 链接:https://www.luogu.org/problem/lists?name=&orderitem=pid&tag=83%2C28 D1T1:carpet 题意简析:一个平面内有多个矩形按顺序覆盖平面,问覆盖后某个点属于哪个矩形. 解题思路:从n~1倒着check点有没有在矩形内即可,时间效率O(n). #include<cstdio> #include<iostream> #include&l

【leetcode】solution in java——Easy2

转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6410409.html 6:Reverse String Write a function that takes a string as input and returns the string reversed. 此题:字符串反转题. 思路:此题大一学C++的时候上机题就做过了,当时思路是:把String转化为char[],从尾到头遍历一次倒序地把字符复制到另一个数组(从头到尾),然后把新数组toStrin

【NOIP2014TG】solution

链接:https://www.luogu.org/problem/lists?name=&orderitem=pid&tag=83|31 D1T1(rps) 题意:给你一个周期,以及胜负关系,求A和B的胜场. 解题思路:暴力抄表,然后暴力计算即可. #include<cstdio> #include<iostream> using namespace std; int a[201],na,nb,b[201],ansa,ansb,n; int f[5][5]{{0,0

【LeetCode】Dungeon Game 解题报告【Solution】

[题目] The demons had captured the princess (P) and imprisoned her in the bottom-right corner of a dungeon. The dungeon consists of M x N rooms laid out in a 2D grid. Our valiant knight (K) was initially positioned in the top-left room and must fight h

【LeetCode】【Solution】Maximum Product Subarray

[题目] Find the contiguous subarray within an array (containing at least one number) which has the largest product. For example, given the array [2,3,-2,4], the contiguous subarray [2,3] has the largest product = 6. [解法] 参考 http://segmentfault.com/blog

【LeetCode】Fraction to Recurring Decimal【Solution】

[题目] Given two integers representing the numerator and denominator of a fraction, return the fraction in string format. If the fractional part is repeating, enclose the repeating part in parentheses. For example, Given numerator = 1, denominator = 2,

【故障处理】告警日志报“ORA-01565 Unable To open Spfile”

[故障处理]告警日志报"ORA-01565 Unable To open Spfile" 1.1  BLOG文档结构图 1.2  故障分析及解决过程 1.2.1  故障环境介绍 项目 source db db 类型 RAC db version 12.1.0.2.0 db 存储 ASM OS版本及kernel版本 SuSE Linux Enterprise Server(SLES 11) 64位 1.2.2  故障发生现象及报错信息 客户的12.1.0.2的RAC库告警日志报ORA-0