matrix_last_acm_2
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的更多相关文章
随机推荐
- Linux redis 配置文件
# Redis configuration file example # Note on units: when memory size is needed, it is possible to sp ...
- Enum枚举类型的使用笔记
好处: 1.可以直接使用switch 2.可以实现toString()方法 笔记: 1.枚举类头部定义的成员变量,可以看做是枚举类的一个实例 public enum Color { RED(" ...
- 【转】MySQL GRANT REVOKE用法
MySQL的权限系统围绕着两个概念: 认证->确定用户是否允许连接数据库服务器 授权->确定用户是否拥有足够的权限执行查询请求等. 如果认证不成功的话,哪么授权肯定是无法进行的. revo ...
- Laravel 5 基础(八)- 模型、控制器、视图基础流程
添加路由 Route::get('artiles', 'ArticlesController@index'); 创建控制器 php artisan make:controller ArticlesCo ...
- 【Delphi】从内存(MemoryStream)使用WMP(WindowsMediaPlayer)控件播放视频音频(Play Video with WMP from MemoryStream)
关键字: MemoryStream.WMP.WindowsMediaPlayer.Play .Load. Delphi.C++.C#.ActiveX控件 作 者: CaiBirdy 问 题:正常使 ...
- IIS上部署MVC网站,打开后ExtensionlessUrlHandler-Integrated-4.0解决办法
IIS上部署MVC网站,打开后ExtensionlessUrlHandler-Integrated-4.0解决方法 IIS上部署MVC网站,打开后500错误:处理程序“ExtensionlessUrl ...
- C语言中断言ASSERT
我一直以为assert仅仅是个报错函数,事实上,它居然是个宏,并且作用并非"报错". 在经过对其进行一定了解之后,对其作用及用法有了一定的了解,assert()的用法像是一种&qu ...
- Stream,Reader/Writer,Buffered的区别(1)
Stream: 是字节流形式,exe文件,图片,视频等.支持8位的字符,用于 ASCII 字符和二进制数据. Reader/Writer: 是字符流,文本文件,XML,txt等,用于16位字符,也就是 ...
- hdu 2544 最短路
题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=2544 最短路 Description 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shi ...
- jdk 1.5
1995.5.23 java语言诞生 sun公司推出java语言的同时,也推出了一系列的开发工具,比如JDK(java development Kit)JVMjava API 时间 版本 API 用途 ...