zoukankan      html  css  js  c++  java
  • Noip 2017 题目整理

    2017Noip:

    小凯的疑惑

    题目描述
    小凯手中有两种面值的金币,两种面值均为正整数且彼此互素。每种金币小凯都有无数个。在不找零的情况下,仅凭这两种金币,有些物品他是无法准确支付的。现在小凯想知道在无法准确支付的物品中,最贵的价值是多少金币?注意:输入数据保证存在小凯无法准确支付的商品。

    输入格式
    输入数据仅一行,包含两个正整数 a和b,它们之间用一个空格隔开,表示小凯手中金币的面值。

    输出格式
    输出文件仅一行,一个正整数N,表示不找零的情况下,小凯用手中的金币不能准确支付的最贵的物品的价值。

    样例输入
    3 7

    样例输出
    11

    样例说明
    小凯手中有面值为3和7的金币无数个,在不找零的前提下无法准确支付价值为 1、2、4、5、8、11的物品,其中最贵的物品价值为11。比11贵的物品都能买到,比如:

    12=3×4+7×0 12 = 3
    13=3×2+7×113 = 3
    14=3×0+7×2 14 = 3
    15=3×5+7×0 15 = 3

    数据范围与提示
    对于30%的数据:1≤a,b≤50
    对于60%的数据: 1≤a,b≤10,000
    对于100%的数据:1≤a,b≤1,000,000,000

    代码实现:

    #include<iostream>
    #include<cmath>
    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=1e5+10;
    typedef long long ll;
    
    ll a,b;
    
    inline ll read() {
        ll n=0,f=1;char ch=getchar();
        while (ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
        while (ch<='9' && ch>='0') {n=(n<<3)+(n<<1)+ch-'0';ch=getchar();}
        return n*f;
    }
    
    
    int main() {
        a=read(),b=read();
        cout<<a*b-a-b<<endl;
    }
    

    时间复杂度

    题目描述

    小明正在学习一种新的编程语言 A++,刚学会循环语句的他激动地写了好多程序并 给出了他自己算出的时间复杂度,可他的编程老师实在不想一个一个检查小明的程序, 于是你的机会来啦!下面请你编写程序来判断小明对他的每个程序给出的时间复杂度是否正确。
    A++语言的循环结构如下:

    F i x y
        循环体
    E
    

    其中F i x y表示新建变量i(变量i不可与未被销毁的变量重名)并初始化为x, 然后判断i和y的大小关系,若i小于等于y则进入循环,否则不进入。每次循环结束后i都会被修改成i+1,一旦i大于y终止循环。

    x和y可以是正整数(x和y的大小关系不定)或变量n是一个表示数据规模的变量,在时间复杂度计算中需保留该变量而不能将其视为常数,该数远大于100。

    “E”表示循环体结束。循环体结束时,这个循环体新建的变量也被销毁。

    注:本题中为了书写方便,在描述复杂度时,使用大写英文字母“O”表示通常意义下“Θ”的概念。

    输入格式:
    输入文件第一行一个正整数t,表示有t(t≤10)个程序需要计算时间复杂度。 每个程序我们只需抽取其中 F i x y和E即可计算时间复杂度。
    注意:循环结构 允许嵌套。

    接下来每个程序的第一行包含一个正整数L和一个字符串,
    L代表程序行数,字符串表示这个程序的复杂度,O(1)表示常数复杂度,O(nw)表示复杂度为nw,其 中w是一个小于100的正整数(输入中不包含引号),输入保证复杂度只有O(1)和O(n^w) 两种类型。

    接下来L行代表程序中循环结构中的F i x y或者E。程序行若以F开头,表示进入一个循环,之后有空格分离的三个字符(串)i x y, 其中i是一个小写字母(保证不为n),表示新建的变量名,x和y 可能是正整数或n ,已知若为正整数则一定小于100。

    程序行若以E开头,则表示循环体结束。

    输出格式:
    输出文件共t行,对应输入的t个程序,每行输出Yes或No或者ERR(输出中不包含引号),若程序实际复杂度与输入给出的复杂度一致则输出Yes,不一致则输出No,若程序有语法错误(其中语法错误只有: ① F和 E不匹配 ②新建的变量与已经存在但未被销毁的变量重复两种情况),则输出ERR 。

    注意:即使在程序不会执行的循环体中出现了语法错误也会编译错误,要输出 ERR。

    输入样例1: 复制
    8
    2 O(1)
    F i 1 1
    E
    2 O(n^1)
    F x 1 n
    E
    1 O(1)
    F x 1 n
    4 O(n^2)
    F x 5 n
    F y 10 n
    E
    E
    4 O(n^2)
    F x 9 n
    E
    F y 2 n
    E
    4 O(n^1)
    F x 9 n
    F y n 4
    E
    E
    4 O(1)
    F y n 4
    F x 9 n
    E
    E
    4 O(n^2)
    F x 1 n
    F x 1 10
    E
    E

    输出样例1: 复制
    Yes
    Yes
    ERR
    Yes
    No
    Yes
    Yes
    ERR

    【输入输出样例解释1】
    第一个程序i从1到1是常数复杂度。
    第二个程序x从1到n是n的一次方的复杂度。
    第三个程序有一个F开启循环却没有 E 结束,语法错误。
    第四个程序二重循环,n的平方的复杂度。
    第五个程序两个一重循环,n的一次方的复杂度。
    第六个程序第一重循环正常,但第二重循环开始即终止(因为n远大于100,100大于4)。
    第七个程序第一重循环无法进入,故为常数复杂度。
    第八个程序第二重循环中的变量x 与第一重循环中的变量重复,出现语法错误②,输出 ERR。

    【数据规模与约定】
    对于30%的数据:不存在语法错误,数据保证小明给出的每个程序的前 L/2行一定为以 F 开头的语句,第L/2+1行至第L行一定为以E开头的语句,L≤10,若x、y均为整数,x一定小于y,且只有y 有可能为n。
    对于50%的数据:不存在语法错误,L≤100,且若x,y均为整数,x一定小于y,且只有y有可能为n。
    对于70%的数据:不存在语法错误,L≤100。
    对于100%的数据:L≤100。

    代码实现:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int N=1e4+10;
    
    int f[201],sz[N];
    int t,s,w,js,d,res,jc,jz;
    int a,b,c,z,y,bz,v,u,q,p,m;
    char S1[101],S2[1001];
    
    inline int read() {
        int n=0,f=1;char ch=getchar();
        while (ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
        while (ch<='9' && ch>='0') {n=(n<<3)+(n<<1)+ch-'0';ch=getchar();}
        return n*f;
    }
    
    inline void init() {
        s=0,w=0,js=0,d=0;
        scanf("%d %s\n",&d,S1+1);
        int l1=strlen(S1+1);
        bz=0;
        for(int i=1;i<=l1;++i) {
            if(S1[i]=='n') bz=1;
            if(S1[i]>='0' && S1[i]<='9') js=js*10+S1[i]-'0';
        }
        res=0,jc=0,jz=0,a=0,v=0,u=0;
        memset(sz,-1,sizeof(sz));
        memset(f,0,sizeof(f));
    }
    
    inline void work() {
        if(u==0) {
            if(jc!=jz) printf("ERR\n");
            else {
                if(bz==0) {
                    if(res==0) printf("Yes\n");
                    else printf("No\n");
                } else if(bz==1) {
                    if(res==js) printf("Yes\n");
                    else printf("No\n");
                }
            }
        }
    }
    
    int main() {
        t=read();
        while(t--) {
            init();
            while(d--) {
                q=0,p=0,m=0;
                gets(S2+1);
                int l2=strlen(S2+1);
                for(int i=1; i<=l2;++i) {
                    if(S2[i]>='0' && S2[i]<='9') {
                        if(m==1) v=1;
                        q=1;
                    }
                    if(S2[i]=='n') {
                        m=1;		
                        if(q==1) p=1;
                    }
                }
                b=0,c=0,z=0,y=l2+1;
                for(int i=1;i<=l2;i++) {
                    if(S2[i]>='0' && S2[i]<='9') c=c*10+S2[i]-'0';
                    if(S2[i]==' ') 
                        if(c!=0) { y=i+1; break; }
                }
                for(int i=y;i<=l2;i++) 
                    if(S2[i]>='0' && S2[i]<='9') z=z*10+S2[i]-'0';
                if(z!=0) 
                    if(c>z) v=1;
                f[sz[s]]=0;
                for(int i=1;i<=l2;i++) {
                    if(S2[i]>='a' && S2[i]<='z') {
                        w++,sz[w]=S2[i],f[S2[i]]++;
                        if(f[S2[i]]>1 && u==0) printf("ERR\n"),u=1;
                        break;
                    }
                }
                for(int i=1;i<=l2;i++) {
                    if(S2[i]=='F') {
                        jc++;
                        if(p==1) {
                            a++;
                            if(v==0) res=max(res,a);
                        }
                    }
                    if(S2[i]=='E') {
                        jz++;
                        if(a>0) {
                            a--;
                            if(a==0) v=0;
                        }
                        f[sz[w]]--,w--;
                    }
                }
            }
            work();
        }
        return 0;
    }
    

    逛公园

    题目描述

    策策同学特别喜欢逛公园。公园可以看成一张N个点M条边构成的有向图,且没有 自环和重边。其中1号点是公园的入口,N号点是公园的出口,每条边有一个非负权值, 代表策策经过这条边所要花的时间。策策每天都会去逛公园,他总是从1号点进去,从N号点出来。
    策策喜欢新鲜的事物,它不希望有两天逛公园的路线完全一样,同时策策还是一个 特别热爱学习的好孩子,它不希望每天在逛公园这件事上花费太多的时间。如果1号点 到N号点的最短路长为d,那么策策只会喜欢长度不超过d+K的路线。
    策策同学想知道总共有多少条满足条件的路线,你能帮帮它吗?为避免输出过大,答案对P取模。如果有无穷多条合法的路线,请输出−1。

    输入输出格式
    输入格式:
    第一行包含一个整数 TT, 代表数据组数。

    接下来TT组数据,对于每组数据: 第一行包含四个整数 N,M,K,P,每两个整数之间用一个空格隔开。

    接下来M行,每行三个整数a_i,b_i,c_i,代表编号为a_i,b_i的点之间有一条权值为 c_i的有向边,每两个整数之间用一个空格隔开。

    输出格式:
    输出文件包含T行,每行一个整数代表答案。

    输入样例1: 复制
    2
    5 7 2 10
    1 2 1
    2 4 0
    4 5 2
    2 3 2
    3 4 1
    3 5 2
    1 5 3
    2 2 0 10
    1 2 0
    2 1 0

    输出样例1: 复制
    3
    -1

    【样例解释1】
    对于第一组数据,最短路为3。 $1 – 5, 1 – 2 – 4 – 5, 1 – 2 – 3 – 5$ 为 3 条合法路径。

    【测试数据与约定】
    对于不同的测试点,我们约定各种参数的规模不会超过如下

    测试点编号 T N M K 是否有0边
    1 5 5 10 0
    2 5 1000 2000 0
    3 5 1000 2000 50
    4 5 1000 2000 50
    5 5 1000 2000 50
    6 5 1000 2000 50
    7 5 100000 200000 0
    8 3 100000 200000 50
    9 3 100000 200000 50
    10 3 100000 200000 50

    对于 100%的数据, 1≤P≤10^9,1≤ai,bi≤N , 1≤ci≤1000.

    数据保证:至少存在一条合法的路线。

    代码实现:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int N=1e5+10;
    const int M=1e5*2+10;
    const int inf=0x3f;
    
    int T,n,m,k,p,js,bz,ans,mod;
    int head[M],dis[N],vis[N],f[M][60],a[M][60];
    
    struct node {
        int nxt,u,v,val;
    }e[M];
    
    inline int read() {
        int n=0,f=1;char ch=getchar();
        while (ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
        while (ch<='9' && ch>='0') {n=(n<<3)+(n<<1)+ch-'0';ch=getchar();}
        return n*f;
    }
    
    inline void add_edge(int u,int v,int w) {
        e[++js].v=v,e[js].u=u,e[js].val=w;
        e[js].nxt=head[u],head[u]=js;
    }
    
    inline void spfa() {
        queue<int > q;
        memset(vis,0,sizeof(vis));
        memset(dis,inf,sizeof(dis));
        dis[1]=0;
        q.push(1);
        while (!q.empty()) {
            int u=q.front();
            q.pop();
            vis[u]=0;
            for(int i=head[u];i;i=e[i].nxt) {
                int v=e[i].v;
                if(dis[v]>dis[u]+e[i].val) {
                    dis[v]=dis[u]+e[i].val;
                    if(!vis[v]) {
                        vis[v]=1;
                        q.push(v);
                    }
                } 
            }
        }
    }
    
    int dfs(int u,int z) {
        if(a[u][z]==1 || bz==1) return bz=1;
        if(a[u][z]==2) return f[u][z]; 
        a[u][z]=1;
        for(int i=head[u];i;i=e[i].nxt) {
            int v=e[i].v,res=z+dis[u]-dis[v]-e[i].val;
            if(res>k || res<0) continue ;
            f[u][z]+=dfs(v,res),f[u][z]%=mod; 
        }
        a[u][z]=2;
        return f[u][z];
    }
    
    int main() {
        T=read();
        while (T--) {
            int u,v,val;
            memset(head,0,sizeof(head));
            memset(f,0,sizeof(f));	
            memset(a,0,sizeof(a));
            js=0;
            n=read(),m=read(),k=read(),mod=read();
            for(int i=1;i<=m;++i) {
                u=read(),v=read(),val=read();
                add_edge(u,v,val);
            }
            spfa();
            memset(head,0,sizeof(head));
            for(int i=1;i<=m;++i) {
                swap(e[i].v,e[i].u);
                e[i].nxt=head[e[i].u];
                head[e[i].u]=i;	
            }
            bz=0,f[1][0]=1,ans=0;
            for(int i=0;i<=k;++i) {
                ans+=dfs(n,i),ans%=mod;
                if(bz==1){
                    ans=-1;
                    break;
                }
            }
            printf("%d\n",ans);
        }
        return 0;
    }
    

    奶酪

    题目描述

    现有一块大奶酪,它的高度为h,它的长度和宽度我们可以认为是无限大的,奶酪 中间有许多 半径相同的球形空洞。我们可以在这块奶酪中建立空间坐标系,在坐标系中, 奶酪的下表面为z=0,奶酪的上表面为z=h。

    现在,奶酪的下表面有一只小老鼠Jerry,它知道奶酪中所有空洞的球心所在的坐 标。如果两个空洞相切或是相交,则 Jerry可以从其中一个空洞跑到另一个空洞,特别地,如果一个空洞与下表面相切或是相交,Jerry 则可以从奶酪下表面跑进空洞;如果一个空洞与上表面相切或是相交,Jerry 则可以从空洞跑到奶酪上表面。位于奶酪下表面的 Jerry 想知道,在不破坏奶酪的情况下,能否利用已有的空洞跑到奶酪的上表面去?
    空间内两点P_1(x_1,y_1,z_1)、P2(x_2,y_2,z_2)的距离公式如下:

    \mathrm{dist}(P_1,P_2)=\sqrt{(x_1-x_2)2+(y_1-y_2)2+(z_1-z_2)^2}

    输入格式:
    每个输入文件包含多组数据。

    第一行,包含一个正整数T,代表该输入文件中所含的数据组数。
    接下来是T组数据,每组数据的格式如下: 第一行包含三个正整数n,h和r,两个数之间以一个空格分开,分别代表奶酪中空洞的数量,奶酪的高度和空洞的半径。

    接下来的n行,每行包含三个整数x,y,z,两个数之间以一个空格分开,表示空 洞球心坐标为(x,y,z)。

    输出格式:
    T行,分别对应T组数据的答案,如果在第i组数据中,Jerry 能从下 表面跑到上表面,则输出Yes,如果不能,则输出No (均不包含引号)。

    输入样例#1: 复制
    3
    2 4 1
    0 0 1
    0 0 3
    2 5 1
    0 0 1
    0 0 4
    2 5 2
    0 0 2
    2 0 4

    输出样例#1: 复制
    Yes
    No
    Yes

    【输入输出样例 1 说明】

    第一组数据,由奶酪的剖面图可见:
    第一个空洞在(0,0,0)与下表面相切
    第二个空洞在(0,0,4)与上表面相切 两个空洞在(0,0,2)相切输出 Yes

    第二组数据,由奶酪的剖面图可见:
    两个空洞既不相交也不相切输出 No

    第三组数据,由奶酪的剖面图可见:
    两个空洞相交 且与上下表面相切或相交输出 Yes

    【数据规模与约定】
    对于20%的数据,n=1,1≤h,r≤10,000,坐标的绝对值不超过 10,000。
    对于40%的数据,1≤n≤8,1≤h,r≤10,000,坐标的绝对值不超过10,000。
    对于80%的数据,1≤n≤1,000,1≤h,r≤10,000,坐标的绝对值不超过10,000。
    对于 100%100%的数据,1≤n≤1,000,1≤h,r≤1,000,000,000,T≤20,坐标的绝对值不超过1,000,000,000。

    代码实现:

    #include<iostream>
    #include<cmath>
    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=1e3+10;
    typedef double dou;
    typedef long long ll;
    
    int bz=0,n,T;
    int vis[N];
    dou h,r;
    
    
    inline int read() {
        int n=0,f=1;char ch=getchar();
        while (ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
        while (ch<='9' && ch>='0') {n=(n<<3)+(n<<1)+ch-'0';ch=getchar();}
        return n*f;
    }
    
    struct node {
        dou x,y,z;
        bool operator < (const node &a) const {
            return z<a.z;
        }
    }e[N];
    
    inline dou calc(dou a,dou b,dou c,dou A,dou B,dou C) {
        return sqrt((A-a)*(A-a)+(B-b)*(B-b)+(C-c)*(C-c));
    }
    
    inline void dfs(node w,int jc) {
        if(w.z+r>=h) {
            bz=1;
            return ;
        }
        vis[jc]=1;
        for(int i=1;i<=n;++i) {
            if(bz) return;
            if(!vis[i] && calc(w.x,w.y,w.z,e[i].x,e[i].y,e[i].z)<=r*2) dfs(e[i],i);
        }
    }
    
    int main() {
        T=read();
        while (T--) {
            memset(vis,0,sizeof(vis));
            memset(e,0,sizeof(e));
            bz=0;
            scanf("%d%lf%lf",&n,&h,&r);
            for(int i=1;i<=n;++i) scanf("%lf%lf%lf",&e[i].x,&e[i].y,&e[i].z);
            sort(e+1,e+n+1);
            for(int i=1;i<=n;++i)
                if(e[i].z-r<=0) dfs(e[i],i);
            if(bz) printf("Yes\n");
            else printf("No\n");
        }
        return 0;
    }
    

    宝藏(50fen)

    题目描述

    参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了n个深埋在地下的宝藏屋,也给出了这n个宝藏屋之间可供开发的m 条道路和它们的长度。

    小明决心亲自前往挖掘所有宝藏屋中的宝藏。但是,每个宝藏屋距离地面都很远, 也就是说,从地面打通一条到某个宝藏屋的道路是很困难的,而开发宝藏屋之间的道路 则相对容易很多。小明的决心感动了考古挖掘的赞助商,赞助商决定免费赞助他打通一条从地面到某个宝藏屋的通道,通往哪个宝藏屋则由小明来决定。

    在此基础上,小明还需要考虑如何开凿宝藏屋之间的道路。已经开凿出的道路可以 任意通行不消耗代价。每开凿出一条新道路,小明就会与考古队一起挖掘出由该条道路 所能到达的宝藏屋的宝藏。另外,小明不想开发无用道路,即两个已经被挖掘过的宝藏 屋之间的道路无需再开发。

    新开发一条道路的代价是: L×K
    L代表这条道路的长度,K代表从赞助商帮你打通的宝藏屋到这条道路起点的宝藏屋所经过的 宝藏屋的数量(包括赞助商帮你打通的宝藏屋和这条道路起点的宝藏屋) 。

    请你编写程序为小明选定由赞助商打通的宝藏屋和之后开凿的道路,使得工程总代价最小,并输出这个最小值。

    输入格式:
    第一行两个用空格分离的正整数n,m,代表宝藏屋的个数和道路数。

    接下来m行,每行三个用空格分离的正整数,分别是由一条道路连接的两个宝藏 屋的编号(编号为1-n),和这条道路的长度v。

    输出格式:
    一个正整数,表示最小的总代价。

    输入样例#1: 复制
    4 5
    1 2 1
    1 3 3
    1 4 1
    2 3 4
    3 4 1

    输出样例#1: 复制
    4

    输入样例#2: 复制
    4 5
    1 2 1
    1 3 3
    1 4 1
    2 3 4
    3 4 2

    输出样例#2: 复制
    5

    【样例解释1】

    小明选定让赞助商打通了1号宝藏屋。小明开发了道路1→2,挖掘了2号宝 藏。开发了道路1→4,挖掘了4号宝藏。还开发了道路 4→3,挖掘了3号宝 藏。工程总代价为:1×1+1×1+1×2=4

    【样例解释2】

    小明选定让赞助商打通了1号宝藏屋。小明开发了道路1→2,挖掘了2号宝 藏。开发了道路 1→3,挖掘了3号宝藏。还开发了道路 1→4,挖掘了4号宝 藏。工程总代价为:1×1+3×1+1×1=5

    【数据规模与约定】

    对于20%的数据: 保证输入是一棵树,1≤n≤8,v≤5000 且所有的v都相等。
    对于40%的数据:1≤n≤8,0≤m≤1000,v≤5000 且所有的v都相等。
    对于 70%70%的数据:1≤n≤8,0≤m≤1000,v≤5000
    对于 100%100%的数据:1≤n≤12,0≤m≤1000,v≤500000

    #include <cstdio>
    #include <algorithm>
    #include <queue>
    #include <cstring>
    #define inf 2147483647
    using namespace std;
    const int N=1e3+10;
    const int M=50;
    
    int n,m,u,v,val;
    int f[M][M],w[M],vis[M]; 
    
    struct node {
        int u, v;
    }e,e2,past[N]; 
    
    bool operator < (struct node a, struct node b) {
        return w[a.u]*f[a.u][a.v]>w[b.u]*f[b.u][b.v];
    }
    
    inline int read() {
        int n=0,f=1;char ch=getchar();
        while (ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
        while (ch<='9' && ch>='0') {n=(n<<3)+(n<<1)+ch-'0';ch=getchar();}
        return n*f;
    }
    
    inline int dfs(int s) {
        memset(w,0,sizeof(w));
        memset(vis,0,sizeof(vis));
        queue <struct node> q;
        int p=0,ans=0;
        w[s]=1,vis[s]=1;
        for(int i=1;i<=n;++i) {
            if(f[s][i]<inf) {
                e.u=s,e.v=i;
                q.push(e);
            }
        } 
        for(int i=1;i<n;++i) {
            e=q.front(); 
            q.pop();
            while (!q.empty() && ((vis[e.v] || rand()%(n)<1))) {
                if(!vis[e.v]) past[p++]=e;
                e=q.front(); 
                q.pop();
    
            } 
            vis[e.v]=1,w[e.v]=w[e.u]+1;
            if(p-->0)  
                for(;p>=0;--p) q.push(past[p]);
            p=0;
            for(int i=1;i<=n;++i) {
                if(f[e.v][i]<inf && !vis[i]) {
                    e2.u=e.v,e2.v=i;
                    q.push(e2);
                }
            } 
            ans+=f[e.u][e.v]*w[e.u];
        } 
        return ans;
    }
    
    int main() {
        n=read(),m=read();
        for(int i=1;i<=n;++i) 
            for(int j=1;j<=n;++j) f[i][j]=inf;
        for (int i=0;i<m;++i) {
            u=read(),v=read(),val=read();
            f[u][v]=f[v][u]=min(val,f[u][v]);
        } 
        srand(201208);
        int res=inf;
        for(int j=1;j<500;++j) 
            for (int i=1;i<=n;++i) res=min(res,dfs(i));
        printf("%d\n",res);
        return 0;
    }
    

    列队(QAQ不会,以后再研究吧)

    
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    typedef long long ll;
    const int N=1e3+10; 
    const int M=5e6+10;
    
    ll n,m,q,x,y,u,t,k,jc,val;
    ll f[N][N],rt[M],js[M];
    
    struct node {
        ll lc,rc,sum,val;
    }e[M<<2];
    
    inline ll read() {
        ll n=0,f=1;char ch=getchar();
        while (ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
        while (ch<='9' && ch>='0') {n=(n<<3)+(n<<1)+ch-'0';ch=getchar();}
        return n*f;
    }
    
    inline void baoli(ll n,ll m,ll q) {
         for(ll i=1;i<=n;++i) 
            for(ll j=1;j<=m;++j) f[i][j]=(i-1)*m+j;
        while (q--) {
            x=read(),y=read();
            ll u=f[x][y];
            for(ll i=y;i<m;++i) f[x][i]=f[x][i+1];
            for(ll i=x;i<n;++i) f[i][m]=f[i+1][m];
            f[n][m]=u;
            printf("%d\n",u);
        }
    }
    
    inline ll get_(ll l,ll r) {
        if(k==n+1) {
            if(r<=n) return r-l+1;
            if(l<=n) return n-l+1;
            return 0;
        }
        if(r<m) return r-l+1;
        if(l<m) return m-l ;
        return 0;
    }
    
    inline ll query(ll &t,ll x,ll l,ll r) {
        if(!t) {
            t=++jc;
            e[t].sum=get_(l,r);
            if(l==r) {
                if(k<=n) e[t].val=(ll)(k-1)*m+l;
                else e[t].val=(ll)l*m;
            }
        }
        e[t].sum--;
        if(l==r) return e[t].val;
        ll mid=(l+r)>>1;
        if((!e[t].lc && x<=(mid-l+1)) || x<=e[e[t].lc].sum) return query(e[t].lc,x,l,mid);
        else {
            if(!e[t].lc) x-=(mid-l+1); 
            else x-=e[e[t].lc].sum;
            return query(e[t].rc,x,mid+1,r);
        }
    }
    
    inline void update(ll &t,ll x,ll w,ll l,ll r) {
        if(!t) {
            t=++jc;
            e[t].sum=get_(l,r);
            if(l==r) e[t].val=w;
        }
        e[t].sum++;
        if(l==r) return ;
        ll mid=(l+r)>>1;
        if(x<=mid) update(e[t].lc,x,w,l,mid);
        else update(e[t].rc,x,w,mid+1,r);
    }
    
    inline ll work(ll n,ll m,ll q) {
        ll p=max(m,n)+q;
        for(ll i=1;i<=q;++i) {
            cin>>x>>y;
            if(y==m) k=n+1,val=query(rt[k],x,1,p);
            else k=x,val=query(rt[k],y,1,p);
            printf("%lld\n",val);
            k=n+1;
            update(rt[n+1],n+(++js[n+1]),val,1,p); 
            if(y!=m) {
                k=n+1,val=query(rt[k],x,1,p);
                k=x,update(rt[x],m-1+(++js[x]),val,1,p);
            }
        }
        return 0;
    }
    
    int main() {
        n=read(),m=read(),q=read();
       	if(n<=1000 && m<=1000) baoli(n,m,q);
       	else work(n,m,q);
        return 0;
    }
    

  • 相关阅读:

    二分查找法
    LeetCode-Two Sum III
    LeetCode-Add and Search Word
    LeetCode-Longest Substring with At Least K Repeating Characters
    LeetCode-Rearrange String k Distance Apart
    LeetCode-Game of Life
    LeetCode-Walls and Gates
    LeetCode-Water and Jug Problem
    LeetCode-Inorder Successor in BST
  • 原文地址:https://www.cnblogs.com/Darkpurple/p/9724426.html
Copyright © 2011-2022 走看看