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

B 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表示没有,线段树根节点就是两个儿子的二进制或。

 //#define debug
//#define txtout
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<cctype>
#include<ctime>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define mt(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long LL;
const double eps=1e-;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const int M=1e5+;
struct OP{
char str[];
int a,b,c;
}op[M];
int n,m;
#define lrrt int L,int R,int rt
#define iall 1,n,1
#define imid int mid=(L+R)>>1
#define lson L,mid,rt<<1
#define rson mid+1,R,rt<<1|1
struct T{
int state,lazy;
}tree[(M*)<<];
void pushup(int rt){
tree[rt].state=tree[rt<<].state|tree[rt<<|].state;
}
void pushdown(int rt){
if(tree[rt].lazy){
tree[rt<<].lazy=tree[rt].lazy;
tree[rt<<|].lazy=tree[rt].lazy;
tree[rt<<].state=tree[rt].lazy;
tree[rt<<|].state=tree[rt].lazy;
tree[rt].lazy=;
}
}
void build(lrrt){
tree[rt].lazy=;
if(L==R){
tree[rt].state=;
return ;
}
imid;
build(lson);
build(rson);
pushup(rt);
}
void update(int x,int y,int z,lrrt){
if(x<=L&&R<=y){
tree[rt].state=z;
tree[rt].lazy=z;
return ;
}
imid;
pushdown(rt);
if(mid>=x) update(x,y,z,lson);
if(mid<y) update(x,y,z,rson);
pushup(rt);
}
int query(int x,int y,lrrt){
if(x<=L&&R<=y) return tree[rt].state;
imid;
pushdown(rt);
int ans=;
if(mid>=x) ans|=query(x,y,lson);
if(mid<y) ans|=query(x,y,rson);
return ans;
}
void solve(){
build(iall);
for(int i=;i<m;i++){
if(op[i].str[]=='P'){
update(op[i].a,op[i].b,<<(op[i].c-),iall);
continue;
}
op[i].c=query(op[i].a,op[i].b,iall);
}
}
int main(){
#ifdef txtout
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
while(~scanf("%d%d",&n,&m),n|m){
for(int i=;i<m;i++){
scanf("%s%d%d",op[i].str,&op[i].a,&op[i].b);
if(op[i].str[]=='Q') continue;
scanf("%d",&op[i].c);
}
solve();
for(int i=;i<m;i++){
if(op[i].str[]=='P') continue;
bool out=false;
for(int j=;j<;j++){
if((op[i].c>>j)&){
if(out) putchar(' ');
printf("%d",j+);
out=true;
}
}
puts("");
}
}
return ;
}

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

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

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

 //#define debug
//#define txtout
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<cctype>
#include<ctime>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define mt(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long LL;
const double eps=1e-;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const int M=1e2+;
char a[M][M];
int dp[M][M][];
int n;
int dx[]={-,-,,,,,,-};
int dy[]={,,,,,-,-,-};
bool inside(int x,int y){
return x>=&&x<n&&y>=&&y<n;
}
void init_dp(){
for(int i=;i<n;i++){
for(int j=;j<n;j++){
for(int k=;k<;k++){
dp[i][j][k]=;
int tx=i;
int ty=j;
while(inside(tx,ty)&&a[tx][ty]=='.'){
dp[i][j][k]++;
tx+=dx[k];
ty+=dy[k];
}
}
}
}
}
int solve(){
init_dp();
int res=;
for(int i=;i<n;i++){
for(int j=;j<n;j++){
if(a[i][j]=='#') continue;
for(int k=;k<;k++){
int step=;
int tx=i;
int ty=j;
while(inside(tx,ty)&&a[tx][ty]=='.'){
res=max(res,step+dp[tx][ty][(k+)%]);
res=max(res,step+dp[tx][ty][(k-+)%]);
tx+=dx[k];
ty+=dy[k];
step++;
}
}
}
}
return res;
}
int main(){
#ifdef txtout
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
while(~scanf("%d",&n),n){
for(int i=;i<n;i++){
scanf("%s",a[i]);
}
printf("%d\n",solve());
}
return ;
}

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,需要优先队列。

 //#define debug
//#define txtout
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<cctype>
#include<ctime>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define mt(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long LL;
const double eps=1e-;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const int M=1e2+;
char a[M][M];
int n,m;
struct Q{
int x,y,key,state;
}now,pre;
queue<Q> q;
int dist[M][M][][<<];
int length_of_snake;
int snake[M][M];
int dx[]={,,,-};
int dy[]={,-,,};
void init_snake(){
length_of_snake=;
for(int i=;i<n;i++){
for(int j=;j<n;j++){
if(a[i][j]!='S') continue;
snake[i][j]=length_of_snake++;
}
}
}
void init(){
init_snake();
int big=<<length_of_snake;
for(int i=;i<n;i++){
for(int j=;j<n;j++){
for(int k=;k<=m;k++){
for(int s=;s<big;s++){
dist[i][j][k][s]=inf;
}
}
}
}
while(!q.empty()) q.pop();
}
void want_to_push(int x,int y,int key,int state,int step){
if(dist[x][y][key][state]>step){
dist[x][y][key][state]=step;
now.x=x;
now.y=y;
now.key=key;
now.state=state;
q.push(now);
}
}
void get_start(){
for(int i=;i<n;i++){
for(int j=;j<n;j++){
if(a[i][j]!='K') continue;
want_to_push(i,j,,,);
return ;
}
}
}
bool inside(int x,int y){
return x>=&&x<n&&y>=&&y<n;
}
int solve(){
init();
get_start();
while(!q.empty()){
pre=q.front();
q.pop();
for(int i=;i<;i++){
int tx=pre.x+dx[i];
int ty=pre.y+dy[i];
if(!inside(tx,ty)) continue;
if(a[tx][ty]=='#') continue;
int pre_step=dist[pre.x][pre.y][pre.key][pre.state];
if(a[tx][ty]=='T'){
if(pre.key==m) return pre_step+;
want_to_push(tx,ty,pre.key,pre.state,pre_step+);
continue;
}
if(a[tx][ty]=='S'){
if((pre.state>>snake[tx][ty])&){
want_to_push(tx,ty,pre.key,pre.state,pre_step+);
continue;
}
want_to_push(pre.x,pre.y,pre.key,pre.state|(<<snake[tx][ty]),pre_step+);
continue;
}
if(isdigit(a[tx][ty])){
if(pre.key+==a[tx][ty]-''){
want_to_push(tx,ty,pre.key+,pre.state,pre_step+);
continue;
}
}
want_to_push(tx,ty,pre.key,pre.state,pre_step+);
}
}
return -;
}
int main(){
#ifdef txtout
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
while(~scanf("%d%d",&n,&m),n|m){
for(int i=;i<n;i++){
scanf("%s",a[i]);
}
int ans=solve();
if(ans==-){
puts("impossible");
continue;
}
printf("%d\n",ans);
}
return ;
}

H 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 的个数。

 //#define debug
//#define txtout
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<cctype>
#include<ctime>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define mt(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long LL;
const double eps=1e-;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const int M=1e5+;
int n,m;
struct E {
int u,v;
} e[M];
struct C {
int x,y,z;
} c[M];
vector<int> lazy[M];
int answer[M];
int to_id[M];
int big_z;
class Shu_Lian_Pou_Fen { ///树链剖分
static const int MV=1e5+; ///点的个数
struct G {
struct E {
int v,next;
} e[MV<<];
int le,head[MV];
void init(int n) {
le=;
for(int i=; i<=n; i++) head[i]=-;
}
void add(int u,int v) {
e[le].v=v;
e[le].next=head[u];
head[u]=le++;
}
} g;
public:
int n,Index,fa[MV],num[MV],son[MV],dep[MV],sid[MV],top[MV];
void dfs(int u) {
num[u]=;
son[u]=;
for(int i=g.head[u]; ~i; i=g.e[i].next) {
int v=g.e[i].v;
if(v!=fa[u]) {
fa[v]=u;
dep[v]=dep[u]+;
dfs(v);
if(num[son[u]]<num[v]) son[u]=v;
num[u]+=num[v];
}
}
}
void get(int u,int Top) {
sid[u]=++Index;
top[u]=Top;
if(son[u]) get(son[u],Top);
for(int i=g.head[u]; ~i; i=g.e[i].next) {
int v=g.e[i].v;
if(v!=fa[u]&&v!=son[u]) {
get(v,v);
}
}
}
public:
void init(int tn) { ///传入点数下标1 开始
n=tn;
g.init(n);
}
void add(int u,int v) {
g.add(u,v);
g.add(v,u);
}
void solve() {
fa[]=dep[]=num[]=Index=;
dfs();
get(,);
}
void update(int x,int y,int z) {
lazy[x].push_back(z);
lazy[y+].push_back(-z);
}
void work(int x,int y,bool edge_index,int z) { ///边编号(用深度大的点一一对应)传入true,点编号传false
int tx=top[x],ty=top[y];
while(tx!=ty) {
if(dep[tx]<dep[ty]) {
swap(tx,ty);
swap(x,y);
}
update(sid[tx],sid[x],z);
x=fa[tx];
tx=top[x];
}
if(edge_index) {
if(x==y) return ;
if(dep[x]>dep[y]) swap(x,y);
update(sid[son[x]],sid[y],z);
return ;
}
if(dep[x]>dep[y]) swap(x,y);
update(sid[x],sid[y],z);
}
}gx;
void init_lazy() {
gx.init(n);
for(int i=;i<n-;i++){
gx.add(e[i].u,e[i].v);
}
gx.solve();
for(int i=;i<=n;i++){
lazy[i].clear();
}
for(int i=;i<m;i++){
gx.work(c[i].x,c[i].y,false,c[i].z);
}
}
#define lrrt int L,int R,int rt
#define iall 1,big_z,1
#define imid int mid=(L+R)>>1
#define lson L,mid,rt<<1
#define rson mid+1,R,rt<<1|1
struct T{
int value,sum;
}tree[M<<];
void pushup(int rt){
if(tree[rt<<].sum>=tree[rt<<|].sum){
tree[rt].value=tree[rt<<].value;
tree[rt].sum=tree[rt<<].sum;
}
else{
tree[rt].value=tree[rt<<|].value;
tree[rt].sum=tree[rt<<|].sum;
}
if(tree[rt].sum==){
tree[rt].value=;
}
}
void build(lrrt){
if(L==R){
tree[rt].value=L;
tree[rt].sum=;
return ;
}
imid;
build(lson);
build(rson);
pushup(rt);
}
void update(int x,int y,lrrt){
if(L==R){
tree[rt].sum+=y;
return ;
}
imid;
if(mid>=x) update(x,y,lson);
else update(x,y,rson);
pushup(rt);
}
int get_big_z(){
int res=;
for(int i=;i<m;i++){
if(c[res].z<c[i].z){
res=i;
}
}
return c[res].z;
}
void solve() {
if(m==){
for(int i=;i<=n;i++){
answer[i]=;
}
return ;
}
init_lazy();
big_z=get_big_z();
build(iall);
for(int i=;i<=n;i++){
to_id[gx.sid[i]]=i;
}
for(int i=;i<=n;i++){
int len=lazy[i].size();
for(int j=;j<len;j++){
int value=lazy[i][j];
int add=;
if(value<){
value=-value;
add=-;
}
update(value,add,iall);
}
answer[to_id[i]]=tree[].value;
}
}
int main() {
#ifdef txtout
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
while(~scanf("%d%d",&n,&m),n|m) {
for(int i=; i<n-; i++) {
scanf("%d%d",&e[i].u,&e[i].v);
}
for(int i=; i<m; i++) {
scanf("%d%d%d",&c[i].x,&c[i].y,&c[i].z);
}
solve();
for(int i=; i<=n; i++) {
printf("%d\n",answer[i]);
}
}
return ;
}

end

matrix_last_acm_2的更多相关文章

随机推荐

  1. MongoDb gridfs-ngnix文件存储方案 - 图片

    http://www.cnblogs.com/wintersun/p/4622205.html 在各类系统应用服务端开发中,我们经常会遇到文件存储的问题. 常见的磁盘文件系统,DBMS传统文件流存储. ...

  2. Java排序

    给出10个数,使用某种排序方法,按照从小到大的顺序输出个个数. 根据要求,首先得给出这10个数,这里的算法需要一个循环,数据结构需要一个长度为10的整型数组.首先用BufferedReader in= ...

  3. angularjs2 学习笔记(五) http服务

    angular2的http服务是用于从后台程序获取或更新数据的一种机制,通常情况我们需要将与后台交换数据的模块做出angular服务,利用http获取更新后台数据,angular使用http的get或 ...

  4. linux动态库编译和使用详细剖析

    引言 重点讲述linux上使用gcc编译动态库的一些操作.并且对其深入的案例分析.最后介绍一下动态库插件技术, 让代码向后兼容.关于linux上使用gcc基础编译, 预编译,编译,生成机械码最后链接输 ...

  5. DB2数据库之间联邦

    现在有以下两个数据库:sample,QIN 需要在数据库QIN中访问sample中的表ACT 1.数据库编目 C:\Users\QIN>db2 catalog tcpip node OLIVER ...

  6. Hadoop组成

    Hadoop由以下几个子项目组成: Hadoop Common Hadoop体系最底层的一个模块,为Hadoop各子项目提供各种工具,如:配置文件和日志操作等. Avro Avro是doug cutt ...

  7. iOS开发的22个奇谲巧技

    结合自身的实践开发经验总结出了22个iOS开发的小技巧,以非常欢乐的语调轻松解决开发过程中所遇到的各种苦逼难题,光读着便已忍俊不禁. 1. TableView不显示没内容的Cell怎么办? 类似于图1 ...

  8. maven学习手记 - 1

    学习目标 windows下安装maven环境: 使用命令创建maven项目结构: maven项目编译测试打包安装运行: 在maven项目中使用插件.   在windows下安装maven环境 在win ...

  9. .Net开源数据库设计工具Mr.E For Linq (EF 6.1) 教程(三)更新已发布的数据库

    项目发布到服务器后,如果在后期,数据库的结构发生变更,如何更新到服务器呢? 首先,右键点击数据库,导出结构脚本文件 把脚本文件和 Mr.E.rar拷贝到服务器,在服务器解压Mr.E,运行其中的“更新数 ...

  10. 6.Inout双向端口信号处理方法

    Verilog中inout端口的使用方法 (本文中所有Verilog描述仅为展示inout端口的用法,实际描述则需要更丰富的功能描述) Inout端口的使用 在芯片中为了管脚复用,很多管脚都是双向的, ...