noip模拟测试16


T1:Blue

  贪心就完了,显然一只蛤尽量往远跳是最优的,用每次跳跃跨过的石头数更新答案就完了。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<cstdlib>
 7 using namespace std;
 8 const int MAXN=1000005,INF=0x3f3f3f3f;
 9 int T;
10 int n,m,d,L,a[MAXN],ans;
11 inline int R() {
12     int a=0;char c=getchar();
13     while(c>'9'||c<'0')c=getchar();
14     while(c>='0'&&c<='9')a=a*10+c-'0',c=getchar();
15     return a;
16 }
17 bool flag;
18 int main() {
19     T=R();
20     while(T--) {
21         n=R();m=R();d=R();L=R();
22         for(int i=1;i<=n;i++) a[i]=R();
23         a[0]=0;a[n+1]=L;ans=m;
24         int now=0;
25         for(int i=0;i<=n+1;i++) {
26             while(now!=n+1&&a[now+1]-a[i]<=d) ++now;
27             if(i==now) {
28                 printf("0\n"),flag=1;
29                 break;
30             }
31             if(now==n+1) break;
32             ans=min(ans,now-i);
33         }
34         if(!flag) {
35             if(ans==m) printf("Excited\n");
36             else printf("%d\n",ans);
37         }
38         flag=0;
39     }
40     return 0;
41 }
t1 Code


T2:Weed

  用线段树维护操作序列,难点在pushup怎么写,考虑每个节点维护三个信息:

  还能删几层,还剩几层,剩下的高度和

  前两个信息可以通过简单的判断$O(1)$计算

  第三个信息可以向下递归计算,具体实现看代码的ask函数

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<cstdlib>
using namespace std;
const int MAXN=300005;
int m,q;
struct opt {
    int k,v;
}o[MAXN];
struct node {
    int l,r,sum,c,e;
}tr[MAXN*4];
int ask(int p,int e) {
    if(e==tr[p<<1|1].c) return tr[p].sum-tr[p<<1|1].sum;
    if(e<tr[p<<1|1].c) return tr[p].sum-tr[p<<1|1].sum+ask(p<<1|1,e);
    return ask(p<<1,e-tr[p<<1|1].c+tr[p<<1|1].e);
}
void up(int p) {
    if(tr[p<<1|1].e>=tr[p<<1].c) {
        tr[p].e=tr[p<<1].e+tr[p<<1|1].e-tr[p<<1].c;
        tr[p].c=tr[p<<1|1].c;
        tr[p].sum=tr[p<<1|1].sum;
    } else if(!tr[p<<1|1].e) {
        tr[p].c=tr[p<<1].c+tr[p<<1|1].c;
        tr[p].sum=tr[p<<1].sum+tr[p<<1|1].sum;
        tr[p].e=tr[p<<1].e;
    } else {
        tr[p].e=tr[p<<1].e;
        tr[p].c=tr[p<<1|1].c+tr[p<<1].c-tr[p<<1|1].e;
        tr[p].sum=tr[p<<1|1].sum+ask(p<<1,tr[p<<1|1].e);
    }
}
void build(int p,int l,int r) {
    tr[p].l=l,tr[p].r=r;
    if(l==r) {
        tr[p].sum=o[l].k?0:o[l].v;
        tr[p].c=o[l].k?0:1;
        tr[p].e=o[l].k?o[l].v:0;
        return;
    }
    int mid=(l+r)>>1;
    build(p<<1,l,mid);
    build(p<<1|1,mid+1,r);
    up(p);
}
void change(int p,int x,int k,int c) {
    if(tr[p].l==tr[p].r) {
        tr[p].sum=k?0:c;
        tr[p].c=k?0:1;
        tr[p].e=k?c:0;
        return;
    }
    int mid=(tr[p].l+tr[p].r)>>1;
    if(x<=mid) change(p<<1,x,k,c);
    else change(p<<1|1,x,k,c);
    up(p);
}
int main() {
    scanf("%d%d",&m,&q);
    for(int i=1;i<=m;i++) scanf("%d%d",&o[i].k,&o[i].v);
    build(1,1,m);
    for(int i=1,aa,bb,cc;i<=q;i++) {
        scanf("%d%d%d",&aa,&bb,&cc);
        change(1,aa,bb,cc);
        printf("%d\n",tr[1].sum);
    }
    return 0;
}
t2 Code

ps:一道相似的题——楼房重建



T3:Drink

  链表神题

  对于每个点(可以看做一个人),规定一个正方向(面朝哪边)

  并记录在这个方向下该点的前后左右分别是那些点

  (以这个人的视角看他的前后左右分别是谁)

  对于一次修改来说,只需要修改正方形边界上人的信息

  注意,不需要也不能记录每个人的方向,因为这样会使修改的复杂度降至$O(n^2)$

  只能记录某一个人(比如左上角)的方向和编号

  再用前后左右的信息推出其他人的方向

  1 #include<cmath>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<iostream>
  6 #include<cstdlib>
  7 #include<queue>
  8 #include<vector>
  9 using namespace std;
 10 const int MAXN=2005;
 11 int n,m,q,s[MAXN][MAXN];
 12 /*
 13       0
 14     3 x 1
 15       2
 16 */
 17 struct Point {
 18     int id;
 19     Point() {id=0;}
 20     int x() {
 21         return (id-1)/m+1;
 22     }
 23     int y() {
 24         return (id-1)%m+1;
 25     }
 26 }fp,tmp[8][MAXN];
 27 int fd,tmpd[8][MAXN];
 28 bool operator == (const Point &aa,const Point &bb) {
 29     return aa.id==bb.id;
 30 }
 31 Point New(int _x,int _y) {
 32     Point ret;
 33     ret.id=(_x-1)*m+_y;
 34     return ret;
 35 }
 36 struct Node {
 37     Point p[4];
 38 }a[MAXN][MAXN];
 39 inline int my_d(int d,int opt) {
 40     return (opt-d+4)%4;
 41 }
 42 Point get_p(Point p,int d,int opt) {
 43     //面向d的点p的opt方向的点
 44     return a[p.x()][p.y()].p[my_d(d,opt)];
 45 }
 46 int get_d(Point lp,Point p,int d,int opt) {
 47     //面向d的点lp的opt方向的点p的方向
 48     int topt=(opt+2)%4;
 49     for(int i=0;i<4;i++)
 50         if(get_p(p,i,topt)==lp) return i;
 51     return -1;
 52 }
 53 void move(Point &p,int &d,int opt) {
 54     Point tp=p;
 55     p=get_p(p,d,opt);
 56     d=get_d(tp,p,d,opt);
 57 }
 58 void modify(Point p,int d,Point c) {
 59     //将p点的d方向上的点改为c
 60     a[p.x()][p.y()].p[d]=c;
 61 }
 62 void change(int x,int y,int c) {
 63     Point np=fp;
 64     int nd=fd;
 65     for(int i=1;i<x;i++) move(np,nd,2);
 66     for(int i=1;i<y;i++) move(np,nd,1);
 67     for(int i=1;i<=c;move(np,nd,1),++i) {
 68         tmp[0][i]=np,tmp[4][i]=get_p(np,nd,0);
 69         tmpd[0][i]=nd,tmpd[4][i]=get_d(np,tmp[4][i],nd,0);
 70     }
 71     move(np,nd,3);
 72     for(int i=1;i<=c;move(np,nd,2),++i) {
 73         tmp[1][i]=np,tmp[5][i]=get_p(np,nd,1);
 74         tmpd[1][i]=nd,tmpd[5][i]=get_d(np,tmp[5][i],nd,1);
 75     }
 76     move(np,nd,0);
 77     for(int i=1;i<=c;move(np,nd,3),++i) {
 78         tmp[2][i]=np,tmp[6][i]=get_p(np,nd,2);
 79         tmpd[2][i]=nd,tmpd[6][i]=get_d(np,tmp[6][i],nd,2);
 80     }
 81     move(np,nd,1);
 82     if(x==1&&y==1) fp=np,fd=(nd+1)%4;
 83     for(int i=1;i<=c;move(np,nd,0),++i) {
 84         tmp[3][i]=np,tmp[7][i]=get_p(np,nd,3);
 85         tmpd[3][i]=nd,tmpd[7][i]=get_d(np,tmp[7][i],nd,3);
 86     }
 87     for(int i=0;i<4;i++)
 88         for(int j=1;j<=c;j++)
 89             modify(tmp[i][j],my_d(tmpd[i][j],i),tmp[(i+1)%4+4][j]);
 90     for(int i=4;i<8;i++)
 91         for(int j=1;j<=c;j++)
 92             modify(tmp[i][j],my_d(tmpd[i][j],(i+2)%4),tmp[(i-1)%4][j]);
 93 }
 94 void print() {
 95     Point xp=fp,yp;
 96     int xd=fd,yd;
 97     for(int i=1;i<=n;move(xp,xd,2),++i) {
 98         yp=xp;yd=xd;
 99         for(int j=1;j<=m;move(yp,yd,1),++j)
100             printf("%d ",s[yp.x()][yp.y()]);
101         printf("\n");
102     }
103 }
104 int main() {
105     scanf("%d%d%d",&n,&m,&q);
106     for(int i=0;i<=n+1;i++)
107         for(int j=0;j<=m+1;j++) {
108             if(i!=0&&i!=n+1&&j!=0&&j!=m+1)
109                 scanf("%d",&s[i][j]);
110             if(i!=0) a[i][j].p[0]=New(i-1,j);
111             if(i!=n+1) a[i][j].p[2]=New(i+1,j);
112             if(j!=0) a[i][j].p[3]=New(i,j-1);
113             if(j!=m+1) a[i][j].p[1]=New(i,j+1);
114         }
115     fp=New(1,1);fd=0;
116     for(int i=1,aa,bb,cc;i<=q;i++) {
117         scanf("%d%d%d",&aa,&bb,&cc);
118         change(aa,bb,cc);
119     }
120     print();
121     return 0;
122 }
t3 Code

猜你喜欢

转载自www.cnblogs.com/Gkeng/p/11354144.html