POJ刷题记录 (。・`ω´・)(Progress:6/50)
1743:前后作差可以转化成不可重叠最长公共字串问题,运用后缀数组解决(参考罗穗骞神犇的论文)
#include <cstdio>
#include <cstring>
#include <algorithm>
;
;
int code[maxL];
int len;
int sa[maxL];
int sr[maxL];
int ht[maxL];
int stp[maxL];
int rdx[maxL];
bool input()
{
scanf("%d",&len);
if(!len) return false;
code[]=;
;i<=len;i++)
scanf("%d",code+i);
;i<len;i++)
code[i]=(code[i+]-code[i]+maxV); //range:[1,175]
len--;
return true;
}
void buildSA()
{
;i<=;i++) rdx[i]=;
;i<=len;i++) ++rdx[code[i]];
;i<=;i++) rdx[i]+=rdx[i-];
;i<=len;i++) sr[i]=rdx[code[i]];
;step<len;step<<=)
{
memset(rdx,,sizeof(rdx));
rdx[]=step;
;i+step<=len;i++) ++rdx[sr[i+step]];
;i<=len;i++) rdx[i]+=rdx[i-];
for(int i=len;i;i--) {
;
stp[rdx[sk]--]=i;
}
memset(rdx,,sizeof(rdx));
;i<=len;i++) ++rdx[sr[i]];
;i<=len;i++) rdx[i]+=rdx[i-];
for(int i=len;i;i--) {
int& cur=stp[i];
sa[rdx[sr[cur]]--]=cur;
}
]]=;
bool ok=true;
;i<=len;i++)
{
int& cur=sa[i];
];
;
;
if(sr[cur]==sr[prev] && csk==psk)
ok=false,srt[cur]=srt[prev];
else srt[cur]=i;
}
memcpy(sr,srt,sizeof(sr));
if(ok) break;
}
}
void calcHeight()
{
ht[]=;
;i<=len;i++)
{
int& cr=sr[i];
) {
ht[cr]=; continue;
}
ht[cr]=ht[sr[i-]]?(ht[sr[i-]]-):;
]+ht[cr]];ht[cr]++);
}
}
bool check(int subLen)
{
],mn=sa[];
;i<=len;i++)
{
if(ht[i]>=subLen)
{
mx=std::max(mx,sa[i]);
mn=std::min(mn,sa[i]);
if(mx-mn>=subLen) return true;
}
else mx=mn=sa[i];
}
return false;
}
int solve()
{
buildSA();
calcHeight();
,right=len;
while(left<=right)
{
;
;
;
}
)?right+:;
}
int main()
{
while(input()) printf("%d\n",solve());
;
}
Problem:POJ P1743
2516:对于每一种货物分别跑一遍最小费用最大流
输入时需注意,如果一组数据处理到一半就可以判定无解,那么必须将这组数据读完才能处理下一组
#include <cstdio>
#include <cstring>
#include <algorithm>
;
][];
][];
int N,M,K;
int sink;
][];
][];
bool check(int tp)
{
,totd=;
;i<=N;i++) totd+=dem[i][tp];
;i<=M;i++) tots+=str[i][tp];
return tots>=totd;
}
void readRem(int ct)
{
while(ct--)
{
int v;
;i<=N;i++)
;j<=M;j++)
scanf("%d",&v);
}
}
#include <queue>
];
];
];
bool spfa()
{
;
std::queue<int> que;
memset(inq,,sizeof(inq));
memset(prev,,sizeof(prev));
;i<=sink;i++) dist[i]=inf;
que.push();
while(!que.empty())
{
int cur=que.front();
inq[cur]=false;
que.pop();
;v<=sink;v++)
if(cp[cur][v])
{
if(dist[v]>dist[cur]+cost[cur][v])
{
dist[v]=dist[cur]+cost[cur][v];
prev[v]=cur;
if(!inq[v])
{
inq[v]=true;
que.push(v);
}
}
}
}
return dist[sink]<inf;
}
int maxFlow()
{
;
while(spfa())
{
int fl=inf;
for(int v=sink;v;v=prev[v])
{
int& p=prev[v];
fl=std::min(fl,cp[p][v]);
}
for(int v=sink;v;v=prev[v])
{
int& p=prev[v];
cp[p][v]-=fl;
cp[v][p]+=fl;
res+=fl*cost[p][v];
}
}
return res;
}
bool proc()
{
scanf("%d%d%d",&N,&M,&K);
if(!N) return false;
sink=N+M+;
;i<=N;i++)
;j<=K;j++)
scanf("%d",dem[i]+j);
;i<=M;i++)
;j<=K;j++)
scanf("%d",str[i]+j);
;
;tp<=K;tp++)
{
if(!check(tp))
{
printf("-1\n");
readRem(K-tp+);
return true;
}
memset(cp,,sizeof(cp));
memset(cost,,sizeof(cost));
;i<=M;i++) cp[][i]=str[i][tp];
;i<=N;i++) cp[i+M][sink]=dem[i][tp];
;i<=N;i++)
;j<=M;j++)
{
scanf("%d",cost[j]+M+i);
cost[M+i][j]=-cost[j][M+i];
cp[j][M+i]=inf;
}
ans+=maxFlow();
}
printf("%d\n",ans);
return true;
}
int main()
{
while(proc());
;
}
Problem:POJ P2516
3261:可重叠的k次最长公共字串,思想和P1743类似,二分答案,对height分层(还是参考论文)
如果对数值进行离散化的话可以节省空间,不过我懒得写了(* ̄∇ ̄*)
偶尔用用模板就是爽(*゚▽゚*)
#include <cstdio>
#include <cstring>
#include <algorithm>
;
;
int code[maxL];
int len,K;
int sa[maxL];
int sr[maxL];
int ht[maxL];
int stp[maxL];
];
void input()
{
scanf("%d%d",&len,&K);
;i<=len;i++)
scanf("%d",code+i);
}
void buildSA()
{
memset(rdx,,sizeof(rdx));
;i<=len;i++) ++rdx[code[i]];
;i<=apb;i++) rdx[i]+=rdx[i-];
;i<=len;i++) sr[i]=rdx[code[i]];
;step<len;step<<=)
{
memset(rdx,,sizeof(rdx));
rdx[]=step;
;i+step<=len;i++) ++rdx[sr[i+step]];
;i<=len;i++) rdx[i]+=rdx[i-];
for(int i=len;i;i--) {
;
stp[rdx[sk]--]=i;
}
memset(rdx,,sizeof(rdx));
;i<=len;i++) ++rdx[sr[i]];
;i<=len;i++) rdx[i]+=rdx[i-];
for(int i=len;i;i--) {
int& cur=stp[i];
sa[rdx[sr[cur]]--]=cur;
}
]]=;
bool ok=true;
;i<=len;i++)
{
int& cur=sa[i];
];
;
;
if(sr[cur]==sr[prev] && csk==psk)
ok=false,srt[cur]=srt[prev];
else srt[cur]=i;
}
memcpy(sr,srt,sizeof(sr));
if(ok) break;
}
}
void calcHeight()
{
ht[]=;
;i<=len;i++)
{
int& cr=sr[i];
) {
ht[cr]=; continue;
}
ht[cr]=ht[sr[i-]]?(ht[sr[i-]]-):;
]+ht[cr]];ht[cr]++);
}
}
bool check(int subLen)
{
;
;i<=len;i++)
{
if(ht[i]>=subLen) {
if((++cnt)>=K) return true;
}
;
}
return false;
}
int solve()
{
buildSA();
calcHeight();
,right=len;
while(left<=right)
{
;
;
;
}
return right;
}
int main()
{
input(); printf("%d\n",solve());
;
}
Problem:POJ P3261
3368:对单调不递减数列求区间众数,把相同的数合并成一个区间,然后对这些区间进行操作即可
#include <cstdio>
#include <cstring>
#include <algorithm>
;
;
int from[maxN];
int to[maxN];
int rgCnt;
int st[logN][maxN];
int N,Q;
bool input()
{
scanf("%d",&N);
if(!N) return false;
scanf("%d",&Q);
int last=0x90000000;
int v;
rgCnt=;
;i<=N;i++)
{
scanf("%d",&v);
if(v>last)
{
to[rgCnt]=i-;
from[++rgCnt]=i;
last=v;
}
}
to[rgCnt]=N;
return true;
}
int log2(int x)
{
;
while(x)
{
++ans;
x>>=;
}
return ans;
}
void initST()
{
;i<=rgCnt;i++)
st[][i]=to[i]-;
int ly=log2(rgCnt);
;i<=ly;i++)
{
<<i)+;
;j<=maxj;j++)
st[i][j]=std::max( st[i-][j],st[i-][j+(<<(i-))] );
}
}
int ask(int L,int R)
{
);
-(<<ly)]);
}
int search(int pos)
{
,hi=rgCnt;
while(lo<hi)
{
;
;
else hi=mid;
}
return lo;
}
void solve()
{
int L,R;
int ls,rs;
initST();
while(Q--)
{
scanf("%d%d",&L,&R);
ls=search(L);
rs=search(R);
);
==rs)
printf();
,rs-),
std::max(to[ls]-L,R-));
}
}
int main()
{
while(input()) solve();
;
}
Problem:POJ P3368
3378:DP+SBT优化转移(被long long溢出和高精度卡了很久……>_<)
#include <cstdio>
#include <cstring>
#include <algorithm>
;
typedef long long int64;
struct Node
{
int key;
int64 sum;
int64 val;
];
];
void assign(int k,int64 v)
{
key=k;
sum=val=v;
size[]=size[]=;
ch[]=ch[]=;
}
};
Node sbt[maxN];
int root,used;
void initSbt()
{
root=used=;
}
inline void update(int c)
{
sbt[c].sum=sbt[sbt[c].ch[]].sum+sbt[sbt[c].ch[]].sum+sbt[c].val;
}
int rotate(int c,int dir) //right-rotate if dir==0
{
int next=sbt[c].ch[dir];
sbt[c].ch[dir]=sbt[next].ch[dir^];
sbt[c].size[dir]=sbt[next].size[dir^];
update(c);
sbt[next].ch[dir^]=c;
sbt[next].size[dir^]+=sbt[c].size[dir^]+;
update(next);
return next;
}
int insert_aux(int k,int64 v,int c)
{
if(!c)
{
sbt[++used].assign(k,v);
return used;
}
int dir = (k >= sbt[c].key); //0 is left; 1 is right
sbt[c].ch[dir]=insert_aux(k,v,sbt[c].ch[dir]);
++sbt[c].size[dir];
update(c);
])
return rotate(c,dir);
] > sbt[c].size[dir^])
{
sbt[c].ch[dir]=rotate(sbt[c].ch[dir],dir^);
return rotate(c,dir);
}
else return c;
}
inline void insert(int k,int64 v)
{
root=insert_aux(k,v,root);
}
int64 ask(int mxk)
{
int64 ans=;
int cur=root;
while(cur)
{
if(mxk<=sbt[cur].key)
cur=sbt[cur].ch[];
else
{
ans+=(sbt[sbt[cur].ch[]].sum+sbt[cur].val);
cur=sbt[cur].ch[];
}
}
return ans;
}
int a[maxN];
int64 dp[maxN];
int N;
bool input()
{
if(scanf("%d",&N)==EOF) return false;
;i<=N;i++) scanf("%d",a+i);
return true;
}
;
;
struct BigInt
{
int dgt[maxD];
int len;
BigInt():len() { memset(dgt,,sizeof(dgt)); }
BigInt operator += (int64 v)
{
;
while(v)
{
dgt[d]+=(v%rdx);
for(int f=d;dgt[f]>=rdx;f++)
{
dgt[f]-=rdx;
++dgt[f+];
}
++d; v/=rdx;
}
if(len<=d)
len=d+(dgt[d]?:);
return *this;
}
void print()
{
");
else
{
printf(]);
;i>=;i--)
printf("%04d",dgt[i]);
}
printf("\n");
}
};
void solve()
{
) { printf("0\n"); return; }
;i<=N;i++) dp[i]=;
;t<=;t++)
{
initSbt();
;i<t;i++)
{
if(dp[i]) insert(a[i],dp[i]);
dp[i]=;
}
for(int i=t;i<=N;i++)
{
int64 temp=dp[i];
dp[i]=ask(a[i]);
insert(a[i],temp);
}
}
BigInt ans;
;i<=N;i++) ans+=dp[i];
ans.print();
}
#include <iostream>
int main()
{
while(input()) solve();
;
}
Problem:POJ P3378
3728:Tarjan求LCA的变种形式,细节比较多
#include <cstdio>
#include <cstring>
#include <algorithm>
;
struct Edge
{
int to,next;
void assign(int t,int n)
{
to=t; next=n;
}
};
Edge elist[maxN<<];
int ehead[maxN];
int ecnt;
void addEdge(int v1,int v2)
{
elist[ecnt].assign(v2,ehead[v1]);
ehead[v1]=ecnt++;
elist[ecnt].assign(v1,ehead[v2]);
ehead[v2]=ecnt++;
}
struct Query
{
int from,to,next;
void assign(int f,int t,int n)
{
from=f; to=t; next=n;
}
};
Query qlist[maxN<<];
int qhead[maxN];
int qcnt;
int ans[maxN];
void addQuery(int v1,int v2)
{
qlist[qcnt].assign(v1,v2,qhead[v1]);
qhead[v1]=qcnt++;
qlist[qcnt].assign(v2,v1,qhead[v2]);
qhead[v2]=qcnt++;
}
struct Proc
{
int idx,next;
void assign(int i,int n)
{
idx=i; next=n;
}
};
Proc plist[maxN];
int phead[maxN];
int pcnt;
void addProc(int v,int idx)
{
plist[pcnt].assign(idx,phead[v]);
phead[v]=pcnt++;
}
void initList()
{
memset(ehead,-,sizeof(ehead));
memset(qhead,-,sizeof(qhead));
memset(phead,-,sizeof(phead));
ecnt=qcnt=pcnt=;
}
int up[maxN],down[maxN],mx[maxN],mn[maxN];
int wgt[maxN];
int N,Q;
void input()
{
initList();
scanf("%d",&N);
;i<=N;i++) scanf("%d",wgt+i);
int v1,v2;
;i<N;i++)
{
scanf("%d%d",&v1,&v2);
addEdge(v1,v2);
}
scanf("%d",&Q);
;i<=Q;i++)
{
scanf("%d%d",&v1,&v2);
addQuery(v1,v2);
}
}
int ftr[maxN];
bool vis[maxN];
void initSet()
{
memset(vis,,sizeof(vis));
memset(up,,sizeof(up));
memset(down,,sizeof(down));
;i<=N;i++)
{
ftr[i]=i;
mx[i]=mn[i]=wgt[i];
}
}
int find(int x)
{
using std::max;
using std::min;
if(ftr[x]==x) return x;
int temp=ftr[x];
ftr[x]=find(ftr[x]);
up[x]=max(mx[temp]-mn[x],max(up[x],up[temp]));
down[x]=max(mx[x]-mn[temp],max(down[x],down[temp]));
mx[x]=max(mx[x],mx[temp]);
mn[x]=min(mn[x],mn[temp]);
return ftr[x];
}
void dfs(int cur)
{
vis[cur]=true;
;q=qlist[q].next)
{
int& to=qlist[q].to;
if(vis[to])
addProc(find(to),q);
}
;e=elist[e].next)
{
int& to=elist[e].to;
if(!vis[to])
{
dfs(to);
ftr[to]=cur;
}
}
using std::max;
;p=plist[p].next)
{
int& idx=plist[p].idx;
int& from=qlist[idx].from;
int& to=qlist[idx].to;
find(from); find(to);
) ans[idx>>]=max(mx[from]-mn[to],max(up[to],down[from]));
]=max(mx[to]-mn[from],max(up[from],down[to]));
}
}
int main()
{
input();
initSet();
dfs();
;i<Q;i++) printf("%d\n",ans[i]);
;
}
Problem:POJ P3728
POJ刷题记录 (。・`ω´・)(Progress:6/50)的更多相关文章
- ZOJ 刷题记录 (。・ω・)ノ゙(Progress:31/50)
[热烈庆祝ZOJ回归] P1002:简单的DFS #include <cstdio> #include <cstring> #include <algorithm> ...
- $2019$ 暑期刷题记录1:(算法竞赛DP练习)
$ 2019 $ 暑期刷题记录: $ POJ~1952~~BUY~LOW, BUY~LOWER: $ (复杂度优化) 题目大意:统计可重序列中最长上升子序列的方案数. 题目很直接的说明了所求为 $ L ...
- PE刷题记录
PE刷题记录 PE60 / 20%dif 这道题比较坑爹. 所有可以相连的素数可以构成一张图,建出这张图,在其中找它的大小为5的团.注意上界的估算,大概在1W以内.1W内有1229个素数,处理出这些素 ...
- leetcode刷题记录--js
leetcode刷题记录 两数之和 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但 ...
- Leetcode刷题记录(python3)
Leetcode刷题记录(python3) 顺序刷题 1~5 ---1.两数之和 ---2.两数相加 ---3. 无重复字符的最长子串 ---4.寻找两个有序数组的中位数 ---5.最长回文子串 6- ...
- 刷题记录:[HarekazeCTF2019]encode_and_encode
目录 刷题记录:[HarekazeCTF2019]encode_and_encode 一.知识点 JSON转义字符绕过 php伪协议 刷题记录:[HarekazeCTF2019]encode_and_ ...
- 刷题记录:[De1CTF 2019]Giftbox && Comment
目录 刷题记录:[De1CTF 2019]Giftbox && Comment 一.知识点 1.sql注入 && totp 2.RCE 3.源码泄露 4.敏感文件读取 ...
- 刷题记录:[强网杯 2019]Upload
目录 刷题记录:[强网杯 2019]Upload 一.知识点 1.源码泄露 2.php反序列化 刷题记录:[强网杯 2019]Upload 题目复现链接:https://buuoj.cn/challe ...
- 刷题记录:[XNUCA2019Qualifier]EasyPHP
目录 刷题记录:[XNUCA2019Qualifier]EasyPHP 解法一 1.error_log结合log_errors自定义错误日志 2.include_path设置包含路径 3.php_va ...
随机推荐
- Frontend Development
原文链接: https://github.com/dypsilon/frontend-dev-bookmarks Frontend Development Looking for something ...
- ios socket通讯注意事项
前段时间,在做objetive-c下的Sokcet通讯,当使用C++程序做服务端时,一切正常;当用JAVA做服务端时,双方收不到数据,在查阅了一些资料后,整理一下注意点 1 消息末尾加回车和换行符 o ...
- for循环++i效率
偶然用到for循环 注意查看了一下 ++i的速度更快 这是PHP语言独有的 其他语言不会有这种情况
- 传统IO与NIO的比较
本文并非Java.io或Java.nio的使用手册,也不是如何使用Java.io与Java.nio的技术文档.这里只是尝试比较这两个包,用最简单的方式突出它们的区别和各自的特性.Java.nio提出了 ...
- c# 字符串转化成声音 分类: C# 2014-09-24 12:20 316人阅读 评论(0) 收藏
说明: (1)支持Window 7系统,但是xp系统智能朗读英文和数字: (2)添加引用 Interop.SpeechLib.dll; (3)使用时调用StringToVoice(str)即可. us ...
- ELK监控系统nginx / mysql慢日志
ELK监控系统nginx / mysql慢日志 elasticsearch logstash kibana ELK监控系统nginx日志 1.环境准备 centos6.8_64 mini IP:192 ...
- nodejs端口被占用。
I had the same issue. I ran: $ ps aux | grep node to get the process id, then: $ sudo kill -9 follow ...
- android-----JNI学习 helloworld
(1)新建android工程 (2)添加NDK路径 (3)添加本地支持 给本地库起名 此时工程目录下会自动生成jni文件夹 此时Makefile也自动生成 LOCAL_PATH := $(call m ...
- Bash简单介绍
Bash不不过一个命令解析程序. 它本身拥有一种程序设计语言,使用这样的语言,能够编写shell脚本来完毕各种各样的工作.而这些工作是使用现成的命令所无法完毕的.Bash脚本能够使用if-then-e ...
- 数学之路-分布式计算-disco(4)
第一个參数iter是一个迭代器,涉及被map函数产生的键和值.它们是reduce实例. 在本例中.单词随机被托付给不同的reduce实例.然后,要单词同样,处理它的reduce也同样.可确保终于合计是 ...