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

 //#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 ;
}

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 ;
}

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 ;
}

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. 3种方式实现Java多线程

    java中实现多线程的方法有两种:继承Thread类和实现runnable接口. 1.继承Thread类,重写父类run()方法 public class thread1 extends Thread ...

  2. MongoDB的主要特性概述

    一.文档数据模型 文档是一组属性名和属性的集合.相较于关系数据库复杂的规范化,面向文档的数据模型很容易以聚合的形式来表示数据.文档采用无Schema的形式,这种做法带来了一定的优势:首先,由应用程序, ...

  3. linux iostat命令详解 磁盘操作监控工具

    Linux系统中的 iostat是I/O statistics(输入/输出统计)的缩写,iostat工具将对系统的磁盘操作活动进行监视. 它的特点是汇报磁盘活动统计情况,同时也会汇报出CPU使用情况. ...

  4. wampserver php多版本5.2--5.6和apche2.2/2.4

    一.准备 wampserver2.5 php5各版本 php5.2到php5.6 apache2.2和apache2.4 二.安装 先成功安装wampserver2.5,如果安装不成功,多是vc11没 ...

  5. 淘宝:OceanBase分布式系统负载均衡案例分享

    Heroku因"随机调度+Rails单线程处理导致延迟增加的负载均衡失败"的案例之后,我们在思考:在负载均衡测试时发现问题并妥善解决的成功经验有没有?于是,挖掘出"淘宝在 ...

  6. USB设备---URB请求快

    1.urb 结构体USB 请求块(USB request block,urb)是USB 设备驱动中用来描述与USB 设备通信所用的基本载体和核心数据结构,非常类似于网络设备驱动中的sk_buff 结构 ...

  7. [terry笔记]RMAN综合学习之备份

    rman是最经济实惠的oracle备份工具,在这里做一个rman的整体学习. 文章中大多是rman命令的语法,还是最好做做实验,以便印象深刻,因为大多数数据库的备份就是按时跑脚本,恢复也不是经常能遇到 ...

  8. iPhone图标及启动画面大小 xcode5

    启动画面 文件名   大小px Default.png 320*480 Default@2x.png 640*960 Default-568h@2x.png 640*1136 图标 文件名  大小px ...

  9. rails的字符编码

    想练练手,随意的写了个登陆页面,简单的只有几行. <%= form_tag('login_check') do -%><%= text_field_tag 'user_name', ...

  10. NOJ1008-第几天

    第几天 时间限制(普通/Java) : 1000 MS/ 3000 MS          运行内存限制 : 65536 KByte总提交 : 2701            测试通过 : 800  ...