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\n",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\n",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\n",answer[i]);
223         }
224     }
225     return 0;
226 }
View Code

 

 

 

end

posted on 2015-10-29 16:41  gaolzzxin  阅读(162)  评论(0编辑  收藏  举报