zoukankan      html  css  js  c++  java
  • matrix_last_acm_2

    2014年广州站网络赛 北大命题 password 123

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=97257#problem/B

    题意:长度为n的墙,一开始1-n都是2号颜色,m次操作,P是将a到b都涂成c号,Q是查询a到b之间内有哪些颜色,从小到大输出。

    解法:颜色只有30种,可以用30位二进制表示某种颜色有或者没有,1表示有,0表示没有,线段树根节点就是两个儿子的二进制或。

      1 //#define debug
      2 //#define txtout
      3 #include<cstdio>
      4 #include<cstdlib>
      5 #include<cstring>
      6 #include<cmath>
      7 #include<cctype>
      8 #include<ctime>
      9 #include<iostream>
     10 #include<algorithm>
     11 #include<vector>
     12 #include<queue>
     13 #include<stack>
     14 #include<map>
     15 #include<set>
     16 #define mt(a,b) memset(a,b,sizeof(a))
     17 using namespace std;
     18 typedef long long LL;
     19 const double eps=1e-8;
     20 const double pi=acos(-1.0);
     21 const int inf=0x3f3f3f3f;
     22 const int M=1e5+10;
     23 struct OP{
     24     char str[4];
     25     int a,b,c;
     26 }op[M];
     27 int n,m;
     28 #define lrrt int L,int R,int rt
     29 #define iall 1,n,1
     30 #define imid int mid=(L+R)>>1
     31 #define lson L,mid,rt<<1
     32 #define rson mid+1,R,rt<<1|1
     33 struct T{
     34     int state,lazy;
     35 }tree[(M*10)<<2];
     36 void pushup(int rt){
     37     tree[rt].state=tree[rt<<1].state|tree[rt<<1|1].state;
     38 }
     39 void pushdown(int rt){
     40     if(tree[rt].lazy){
     41         tree[rt<<1].lazy=tree[rt].lazy;
     42         tree[rt<<1|1].lazy=tree[rt].lazy;
     43         tree[rt<<1].state=tree[rt].lazy;
     44         tree[rt<<1|1].state=tree[rt].lazy;
     45         tree[rt].lazy=0;
     46     }
     47 }
     48 void build(lrrt){
     49     tree[rt].lazy=0;
     50     if(L==R){
     51         tree[rt].state=2;
     52         return ;
     53     }
     54     imid;
     55     build(lson);
     56     build(rson);
     57     pushup(rt);
     58 }
     59 void update(int x,int y,int z,lrrt){
     60     if(x<=L&&R<=y){
     61         tree[rt].state=z;
     62         tree[rt].lazy=z;
     63         return ;
     64     }
     65     imid;
     66     pushdown(rt);
     67     if(mid>=x) update(x,y,z,lson);
     68     if(mid<y)  update(x,y,z,rson);
     69     pushup(rt);
     70 }
     71 int query(int x,int y,lrrt){
     72     if(x<=L&&R<=y) return tree[rt].state;
     73     imid;
     74     pushdown(rt);
     75     int ans=0;
     76     if(mid>=x) ans|=query(x,y,lson);
     77     if(mid<y)  ans|=query(x,y,rson);
     78     return ans;
     79 }
     80 void solve(){
     81     build(iall);
     82     for(int i=0;i<m;i++){
     83         if(op[i].str[0]=='P'){
     84             update(op[i].a,op[i].b,1<<(op[i].c-1),iall);
     85             continue;
     86         }
     87         op[i].c=query(op[i].a,op[i].b,iall);
     88     }
     89 }
     90 int main(){
     91     #ifdef txtout
     92     freopen("in.txt","r",stdin);
     93     freopen("out.txt","w",stdout);
     94     #endif
     95     while(~scanf("%d%d",&n,&m),n|m){
     96         for(int i=0;i<m;i++){
     97             scanf("%s%d%d",op[i].str,&op[i].a,&op[i].b);
     98             if(op[i].str[0]=='Q') continue;
     99             scanf("%d",&op[i].c);
    100         }
    101         solve();
    102         for(int i=0;i<m;i++){
    103             if(op[i].str[0]=='P') continue;
    104             bool out=false;
    105             for(int j=0;j<30;j++){
    106                 if((op[i].c>>j)&1){
    107                     if(out) putchar(' ');
    108                     printf("%d",j+1);
    109                     out=true;
    110                 }
    111             }
    112             puts("");
    113         }
    114     }
    115     return 0;
    116 }
    View Code

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=97257#problem/C

    题意:n*n的矩阵,.可以走,#不能走。8个方向走,上下左右,还有45度的四个方向。最多只能转弯一次且一定要转90度,问最长的路径的长度。

    解法:先预处理出每个点8个方向最远能走的长度。然后枚举每个起点,枚举8个方向,每走一步都尝试左转90和右转90,取最大值。

     1 //#define debug
     2 //#define txtout
     3 #include<cstdio>
     4 #include<cstdlib>
     5 #include<cstring>
     6 #include<cmath>
     7 #include<cctype>
     8 #include<ctime>
     9 #include<iostream>
    10 #include<algorithm>
    11 #include<vector>
    12 #include<queue>
    13 #include<stack>
    14 #include<map>
    15 #include<set>
    16 #define mt(a,b) memset(a,b,sizeof(a))
    17 using namespace std;
    18 typedef long long LL;
    19 const double eps=1e-8;
    20 const double pi=acos(-1.0);
    21 const int inf=0x3f3f3f3f;
    22 const int M=1e2+10;
    23 char a[M][M];
    24 int dp[M][M][8];
    25 int n;
    26 int dx[]={-1,-1,0,1,1,1,0,-1};
    27 int dy[]={0,1,1,1,0,-1,-1,-1};
    28 bool inside(int x,int y){
    29     return x>=0&&x<n&&y>=0&&y<n;
    30 }
    31 void init_dp(){
    32     for(int i=0;i<n;i++){
    33         for(int j=0;j<n;j++){
    34             for(int k=0;k<8;k++){
    35                 dp[i][j][k]=0;
    36                 int tx=i;
    37                 int ty=j;
    38                 while(inside(tx,ty)&&a[tx][ty]=='.'){
    39                     dp[i][j][k]++;
    40                     tx+=dx[k];
    41                     ty+=dy[k];
    42                 }
    43             }
    44         }
    45     }
    46 }
    47 int solve(){
    48     init_dp();
    49     int res=0;
    50     for(int i=0;i<n;i++){
    51         for(int j=0;j<n;j++){
    52             if(a[i][j]=='#') continue;
    53             for(int k=0;k<8;k++){
    54                 int step=0;
    55                 int tx=i;
    56                 int ty=j;
    57                 while(inside(tx,ty)&&a[tx][ty]=='.'){
    58                     res=max(res,step+dp[tx][ty][(k+2)%8]);
    59                     res=max(res,step+dp[tx][ty][(k-2+8)%8]);
    60                     tx+=dx[k];
    61                     ty+=dy[k];
    62                     step++;
    63                 }
    64             }
    65         }
    66     }
    67     return res;
    68 }
    69 int main(){
    70     #ifdef txtout
    71     freopen("in.txt","r",stdin);
    72     freopen("out.txt","w",stdout);
    73     #endif
    74     while(~scanf("%d",&n),n){
    75         for(int i=0;i<n;i++){
    76             scanf("%s",a[i]);
    77         }
    78         printf("%d
    ",solve());
    79     }
    80     return 0;
    81 }
    View Code

     D http://acm.hust.edu.cn/vjudge/contest/view.action?cid=97257#problem/D

    题意:n*n的矩形,K起点,T终点,上下左右走,每一步一秒,到达终点前要集齐m个钥匙,钥匙编号要从小到大收集,第一次遇到的S要多花一秒,问最少几秒完成。

    解法: bfs,状态  x y 拥有钥匙的最大号 key,蛇的状态 state,如果用队列,遇到s时杀了,要停在原地。另一种方法是直接进s,step+=2,需要优先队列。

      1 //#define debug
      2 //#define txtout
      3 #include<cstdio>
      4 #include<cstdlib>
      5 #include<cstring>
      6 #include<cmath>
      7 #include<cctype>
      8 #include<ctime>
      9 #include<iostream>
     10 #include<algorithm>
     11 #include<vector>
     12 #include<queue>
     13 #include<stack>
     14 #include<map>
     15 #include<set>
     16 #define mt(a,b) memset(a,b,sizeof(a))
     17 using namespace std;
     18 typedef long long LL;
     19 const double eps=1e-8;
     20 const double pi=acos(-1.0);
     21 const int inf=0x3f3f3f3f;
     22 const int M=1e2+10;
     23 char a[M][M];
     24 int n,m;
     25 struct Q{
     26     int x,y,key,state;
     27 }now,pre;
     28 queue<Q> q;
     29 int dist[M][M][10][1<<5];
     30 int length_of_snake;
     31 int snake[M][M];
     32 int dx[]={0,0,1,-1};
     33 int dy[]={1,-1,0,0};
     34 void init_snake(){
     35     length_of_snake=0;
     36     for(int i=0;i<n;i++){
     37         for(int j=0;j<n;j++){
     38             if(a[i][j]!='S') continue;
     39             snake[i][j]=length_of_snake++;
     40         }
     41     }
     42 }
     43 void init(){
     44     init_snake();
     45     int big=1<<length_of_snake;
     46     for(int i=0;i<n;i++){
     47         for(int j=0;j<n;j++){
     48             for(int k=0;k<=m;k++){
     49                 for(int s=0;s<big;s++){
     50                     dist[i][j][k][s]=inf;
     51                 }
     52             }
     53         }
     54     }
     55     while(!q.empty()) q.pop();
     56 }
     57 void want_to_push(int x,int y,int key,int state,int step){
     58     if(dist[x][y][key][state]>step){
     59         dist[x][y][key][state]=step;
     60         now.x=x;
     61         now.y=y;
     62         now.key=key;
     63         now.state=state;
     64         q.push(now);
     65     }
     66 }
     67 void get_start(){
     68     for(int i=0;i<n;i++){
     69         for(int j=0;j<n;j++){
     70             if(a[i][j]!='K') continue;
     71             want_to_push(i,j,0,0,0);
     72             return ;
     73         }
     74     }
     75 }
     76 bool inside(int x,int y){
     77     return x>=0&&x<n&&y>=0&&y<n;
     78 }
     79 int solve(){
     80     init();
     81     get_start();
     82     while(!q.empty()){
     83         pre=q.front();
     84         q.pop();
     85         for(int i=0;i<4;i++){
     86             int tx=pre.x+dx[i];
     87             int ty=pre.y+dy[i];
     88             if(!inside(tx,ty)) continue;
     89             if(a[tx][ty]=='#') continue;
     90             int pre_step=dist[pre.x][pre.y][pre.key][pre.state];
     91             if(a[tx][ty]=='T'){
     92                 if(pre.key==m) return pre_step+1;
     93                 want_to_push(tx,ty,pre.key,pre.state,pre_step+1);
     94                 continue;
     95             }
     96             if(a[tx][ty]=='S'){
     97                 if((pre.state>>snake[tx][ty])&1){
     98                     want_to_push(tx,ty,pre.key,pre.state,pre_step+1);
     99                     continue;
    100                 }
    101                 want_to_push(pre.x,pre.y,pre.key,pre.state|(1<<snake[tx][ty]),pre_step+1);
    102                 continue;
    103             }
    104             if(isdigit(a[tx][ty])){
    105                 if(pre.key+1==a[tx][ty]-'0'){
    106                     want_to_push(tx,ty,pre.key+1,pre.state,pre_step+1);
    107                     continue;
    108                 }
    109             }
    110             want_to_push(tx,ty,pre.key,pre.state,pre_step+1);
    111         }
    112     }
    113     return -1;
    114 }
    115 int main(){
    116     #ifdef txtout
    117     freopen("in.txt","r",stdin);
    118     freopen("out.txt","w",stdout);
    119     #endif
    120     while(~scanf("%d%d",&n,&m),n|m){
    121         for(int i=0;i<n;i++){
    122             scanf("%s",a[i]);
    123         }
    124         int ans=solve();
    125         if(ans==-1){
    126             puts("impossible");
    127             continue;
    128         }
    129         printf("%d
    ",ans);
    130     }
    131     return 0;
    132 }
    View Code

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=97257#problem/H

    题意:给一颗树,n个节点。给m次操作,每次操作x到y路径上的每一个点都增加一个种类编号是z的物品,最后问每一个节点 个数最多的种类编号,如果有多个个数相同的种类,输出编号最小的。如果没有物品输出0.

    解法:1.树链剖分转化为一维线段的同样的问题。2.对区间x到y增加一个z,可以用一个数组vector存,x位置存z,y+1位置存-z。把所有的操作都存好后,遍历线段上的点,将该点上vector存的都加入线段树中,最后在线段树查最大个数的下标。线段树1-z,每一个位置代表种类为i 的个数。

      1 //#define debug
      2 //#define txtout
      3 #include<cstdio>
      4 #include<cstdlib>
      5 #include<cstring>
      6 #include<cmath>
      7 #include<cctype>
      8 #include<ctime>
      9 #include<iostream>
     10 #include<algorithm>
     11 #include<vector>
     12 #include<queue>
     13 #include<stack>
     14 #include<map>
     15 #include<set>
     16 #define mt(a,b) memset(a,b,sizeof(a))
     17 using namespace std;
     18 typedef long long LL;
     19 const double eps=1e-8;
     20 const double pi=acos(-1.0);
     21 const int inf=0x3f3f3f3f;
     22 const int M=1e5+10;
     23 int n,m;
     24 struct E {
     25     int u,v;
     26 } e[M];
     27 struct C {
     28     int x,y,z;
     29 } c[M];
     30 vector<int> lazy[M];
     31 int answer[M];
     32 int to_id[M];
     33 int big_z;
     34 class Shu_Lian_Pou_Fen { ///树链剖分
     35     static const int MV=1e5+10; ///点的个数
     36     struct G {
     37         struct E {
     38             int v,next;
     39         } e[MV<<1];
     40         int le,head[MV];
     41         void init(int n) {
     42             le=0;
     43             for(int i=0; i<=n; i++) head[i]=-1;
     44         }
     45         void add(int u,int v) {
     46             e[le].v=v;
     47             e[le].next=head[u];
     48             head[u]=le++;
     49         }
     50     } g;
     51 public:
     52     int n,Index,fa[MV],num[MV],son[MV],dep[MV],sid[MV],top[MV];
     53     void dfs(int u) {
     54         num[u]=1;
     55         son[u]=0;
     56         for(int i=g.head[u]; ~i; i=g.e[i].next) {
     57             int v=g.e[i].v;
     58             if(v!=fa[u]) {
     59                 fa[v]=u;
     60                 dep[v]=dep[u]+1;
     61                 dfs(v);
     62                 if(num[son[u]]<num[v]) son[u]=v;
     63                 num[u]+=num[v];
     64             }
     65         }
     66     }
     67     void get(int u,int Top) {
     68         sid[u]=++Index;
     69         top[u]=Top;
     70         if(son[u]) get(son[u],Top);
     71         for(int i=g.head[u]; ~i; i=g.e[i].next) {
     72             int v=g.e[i].v;
     73             if(v!=fa[u]&&v!=son[u]) {
     74                 get(v,v);
     75             }
     76         }
     77     }
     78 public:
     79     void init(int tn) { ///传入点数下标1 开始
     80         n=tn;
     81         g.init(n);
     82     }
     83     void add(int u,int v) {
     84         g.add(u,v);
     85         g.add(v,u);
     86     }
     87     void solve() {
     88         fa[1]=dep[1]=num[0]=Index=0;
     89         dfs(1);
     90         get(1,1);
     91     }
     92     void update(int x,int y,int z) {
     93         lazy[x].push_back(z);
     94         lazy[y+1].push_back(-z);
     95     }
     96     void work(int x,int y,bool edge_index,int z) { ///边编号(用深度大的点一一对应)传入true,点编号传false
     97         int tx=top[x],ty=top[y];
     98         while(tx!=ty) {
     99             if(dep[tx]<dep[ty]) {
    100                 swap(tx,ty);
    101                 swap(x,y);
    102             }
    103             update(sid[tx],sid[x],z);
    104             x=fa[tx];
    105             tx=top[x];
    106         }
    107         if(edge_index) {
    108             if(x==y) return ;
    109             if(dep[x]>dep[y]) swap(x,y);
    110             update(sid[son[x]],sid[y],z);
    111             return ;
    112         }
    113         if(dep[x]>dep[y]) swap(x,y);
    114         update(sid[x],sid[y],z);
    115     }
    116 }gx;
    117 void init_lazy() {
    118     gx.init(n);
    119     for(int i=0;i<n-1;i++){
    120         gx.add(e[i].u,e[i].v);
    121     }
    122     gx.solve();
    123     for(int i=1;i<=n;i++){
    124         lazy[i].clear();
    125     }
    126     for(int i=0;i<m;i++){
    127         gx.work(c[i].x,c[i].y,false,c[i].z);
    128     }
    129 }
    130 #define lrrt int L,int R,int rt
    131 #define iall 1,big_z,1
    132 #define imid int mid=(L+R)>>1
    133 #define lson L,mid,rt<<1
    134 #define rson mid+1,R,rt<<1|1
    135 struct T{
    136     int value,sum;
    137 }tree[M<<2];
    138 void pushup(int rt){
    139     if(tree[rt<<1].sum>=tree[rt<<1|1].sum){
    140         tree[rt].value=tree[rt<<1].value;
    141         tree[rt].sum=tree[rt<<1].sum;
    142     }
    143     else{
    144         tree[rt].value=tree[rt<<1|1].value;
    145         tree[rt].sum=tree[rt<<1|1].sum;
    146     }
    147     if(tree[rt].sum==0){
    148         tree[rt].value=0;
    149     }
    150 }
    151 void build(lrrt){
    152     if(L==R){
    153         tree[rt].value=L;
    154         tree[rt].sum=0;
    155         return ;
    156     }
    157     imid;
    158     build(lson);
    159     build(rson);
    160     pushup(rt);
    161 }
    162 void update(int x,int y,lrrt){
    163     if(L==R){
    164         tree[rt].sum+=y;
    165         return ;
    166     }
    167     imid;
    168     if(mid>=x) update(x,y,lson);
    169     else       update(x,y,rson);
    170     pushup(rt);
    171 }
    172 int get_big_z(){
    173     int res=0;
    174     for(int i=1;i<m;i++){
    175         if(c[res].z<c[i].z){
    176             res=i;
    177         }
    178     }
    179     return c[res].z;
    180 }
    181 void solve() {
    182     if(m==0){
    183         for(int i=1;i<=n;i++){
    184             answer[i]=0;
    185         }
    186         return ;
    187     }
    188     init_lazy();
    189     big_z=get_big_z();
    190     build(iall);
    191     for(int i=1;i<=n;i++){
    192         to_id[gx.sid[i]]=i;
    193     }
    194     for(int i=1;i<=n;i++){
    195         int len=lazy[i].size();
    196         for(int j=0;j<len;j++){
    197             int value=lazy[i][j];
    198             int add=1;
    199             if(value<0){
    200                 value=-value;
    201                 add=-1;
    202             }
    203             update(value,add,iall);
    204         }
    205         answer[to_id[i]]=tree[1].value;
    206     }
    207 }
    208 int main() {
    209 #ifdef txtout
    210     freopen("in.txt","r",stdin);
    211     freopen("out.txt","w",stdout);
    212 #endif
    213     while(~scanf("%d%d",&n,&m),n|m) {
    214         for(int i=0; i<n-1; i++) {
    215             scanf("%d%d",&e[i].u,&e[i].v);
    216         }
    217         for(int i=0; i<m; i++) {
    218             scanf("%d%d%d",&c[i].x,&c[i].y,&c[i].z);
    219         }
    220         solve();
    221         for(int i=1; i<=n; i++) {
    222             printf("%d
    ",answer[i]);
    223         }
    224     }
    225     return 0;
    226 }
    View Code

    end

  • 相关阅读:
    POJ 1149 PIGS(Dinic最大流)
    HDU 4514 湫湫系列故事——设计风景线(并查集+树形DP)
    [kuangbin带你飞]专题十一 网络流个人题解(L题留坑)
    BZOJ 3931 网络吞吐量(最短路+拆点最大流)
    学习RMQ-ST表
    `这个符号在mysql中的作用
    用一条mysql语句插入多条数据
    Leetcode 257 Binary Tree Paths 二叉树 DFS
    Leetcode 203 Remove Linked List Elements 链表
    Leetcode 38 Count and Say 传说中的递推
  • 原文地址:https://www.cnblogs.com/gaolzzxin/p/4920945.html
Copyright © 2011-2022 走看看