总结:…………我忘了,反正当时T2是写了两个版本对拍,一个是线段树一个是STL乱搞,然后……交了STL版…………WA,线段树……A………………总之还是觉得有时间的话自己写写比较靠谱【23333
T1:
题意:给一个字符串,求有多少个子串可以和这个字符串的前缀匹配(样例:input【aaba】,output【6】,解释:六个子串的下标分别是[1,1],[1,2],[1,3],[1,4],[2,2],[4,4]
思路:
反正一看就可以用KMP搞,想想似乎不太会写KMP,不管了现场推吧哼=、=。
然后……思考思考,似乎ans就是fail树的所有节点深度之和啊
代码:
#include<bits/stdc++.h>
#define MAXN 1000005
using namespace std;
char s[MAXN];
int fail[MAXN];
long long f[MAXN];
long long ans=0;
void KMP (){
int lth=strlen(s+1);
f[1]=1;
for(int i=1,j;i<=lth;++i){
j=fail[i];
while((s[i+1]^s[j+1])&&j) j=fail[j];
if(s[i+1]==s[j+1]) fail[i+1]=j+1,f[i+1]=f[j+1]+1;
else fail[i+1]=0,f[i+1]=1;
ans+=f[i];
}
// for(int i=1;i<=lth;++i) printf(" %c",s[i]);
// puts("");
// for(int i=1;i<=lth;++i) printf("%3d",fail[i]);
// puts("");
}
int main(){
freopen("gene.in","r",stdin);
freopen("gene.out","w",stdout);
scanf("%s",s+1);
KMP();
printf("%lld",ans);
return 0;
}
T2:
题意:给定两个向量(夹角始终小于180°)和若干点的坐标,每个点可以转移到这两个向量夹角之间(包含边界)的地方,求从一个点(任选)出发,最多可以经过多少个点。
思路:
想一想……好像直接搞的话会爆精度还需要特判…………根据高一数学知识,可以用两个线性无关的向量表示二维平面内的任一点(点坐标显然可以当成向量x),于是直接改坐标,推一推公式用这两个向量当x轴和y轴,于是转化成了每个点只能走向它的右上(包含边界)方的点。。。
naive的flaze并没有一眼看出可以直接LIS搞……于是扫了一遍并用线段树更新答案…………写完发现这不是lis吗……裸的那种2333,于是手贱又用lower_bound随便水水地敲了一遍lis…………然后……嗯对拍发现没有问题诶w,交交交……嗯交短的好了,然而……嗯……WA了【并不想debug2333】
代码:
#include<bits/stdc++.h>
#define MAXN 200005
using namespace std; int n;
struct vec{
long long x,y;
vec():x(0),y(0){}
vec(long long x,long long y):x(x),y(y){}
bool operator < (const vec ano) const{
return x==ano.x? y<ano.y:x<ano.x;
}
}V1,V2,rec[MAXN];
inline void get_xy(long long &x,long long &y){
long long a = x*V2.y - V2.x*y;
long long b = V1.x*y - x*V1.y;
x=a,y=b;
}
long long base_y[MAXN],cnt_y;
int dt[MAXN<<2],tag[MAXN<<2];
inline void pushdown(int now,int l,int r){
if(l==r){
dt[now]=max(dt[now],tag[now]);
tag[now]=0;
return ;
}
tag[now<<1]=max(tag[now<<1],tag[now]);
tag[now<<1|1]=max(tag[now<<1|1],tag[now]);
int mid=(l+r)>>1;
if(l==mid) dt[now<<1]=max(dt[now<<1],tag[now]);
if(mid+1==r) dt[now<<1|1]=max(dt[now<<1|1],tag[now]);
tag[now]=0;
}
void modify(int now,int l,int r,int L,int R,int v){
if(L<=l&&r<=R){
tag[now]=max(tag[now],v);
pushdown(now,l,r);
return ;
}
int mid=(l+r)>>1;
if(tag[now]) pushdown(now,l,r);
if(L<=mid) modify(now<<1,l,mid,L,R,v);
if(mid<R) modify(now<<1|1,mid+1,r,L,R,v);
}
int inqry(int now,int l,int r,int pos){
if(l==r) return dt[now];
int mid=(l+r)>>1;
if(tag[now]) pushdown(now,l,r);
if(pos<=mid) return inqry(now<<1,l,mid,pos);
else return inqry(now<<1|1,mid+1,r,pos);
}
int ans=0;
long long read_x,read_y;
int main(){
freopen("sheild.in","r",stdin);
// freopen("sheild.out","w",stdout);
scanf("%d",&n);
scanf("%lld%lld",&read_x,&read_y); V1=vec(read_x,read_y);
scanf("%lld%lld",&read_x,&read_y); V2=vec(read_x,read_y);
for(int i=1;i<=n;++i){
scanf("%lld%lld",&read_x,&read_y);
get_xy(read_x,read_y);
base_y[i]=read_y;
rec[i]=vec(read_x,read_y);
}
sort(base_y+1,base_y+n+1);
cnt_y=unique(base_y+1,base_y+n+1)-base_y-1;
// for(int i=1;i<=cnt_y;++i) printf("y = %d\n",base_y[i]);
V1=vec(1,0),V2=vec(0,1);
sort(rec+1,rec+n+1);
// for(int i=1;i<=n;++i) printf("( %lld , %lld )\n",rec[i].x,rec[i].y);
for(int i=n;i;--i){
int pos_y=lower_bound(base_y+1,base_y+cnt_y+1,rec[i].y)-base_y;
int dd=inqry(1,1,n,pos_y);
ans=max(ans,dd+1);
modify(1,1,n,1,pos_y,dd+1);
}
printf("%d",ans);
return 0;
}
T3
题意:(BZOJ 3832)给一个DAG(不一定联通),求删去一个节点后的最长路最短是多少
思路:
GG
安利popoqqq和heheda的题解……beiyu和claris的也都很稳……
思路超神啊%%%%%%%
好吧不扯了,考虑显然先把DAG转化成拓扑序,然后……然后?没了啊
显然最naive的思路就是分别删去每个点,然后算最长路,如果每次算最长路都是暴力的话显然会T,于是考虑优化一下
删去每个点的时候,只会影响会经过它的最长路,也就是只会影响经过【以它为端点的边】的最长路,而且是使它从路径长度集合中删去。
因为会出现删点后图不连通【或者它自己本来就不连通】的情况,所以要加一个源点,向所有节点连边,再加一个汇点,从所有节点向它连边【
维护每条边所在的最长路的长度,显然可以用【它的起点到源点】的最长路长度加上【它的终点到汇点】的最长路长度来表示。
然后在枚举删去另外的点时,把之前删去的长度加进集合里就好
再想想,就相当于是用一个数据结构,支持 加入,删除,查询最大值=、=
multiset,priority_queue,堆,平衡树,值域线段树……都很靠谱
再稍微搞一下细节……
嗯学会了用priority_queue写支持删除的堆的姿势【对不起我就是菜】
什么……你问我为什么要写读入优化?【艹榜啊x
代码:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define MAXN 500005
#define MAXM 1000005
#define INF 0x3f3f3f3f
using namespace std; int n,m;
int S=0,T=MAXN-1;
//==================================================
struct io_t{
char op[1<<25];
char* s;
int a[24];
char ed[1];
char* t;
io_t():s(op),t(ed){
fread(s,1,
sizeof op,stdin);
}
~io_t(){
fwrite(ed,1,
t-ed,stdout);
}
void scan(char* q){
while(*s<48)
++s;
while(*s>32)
*q++=*s++;
*q=0;
}
void print(const
char* q){
while(*q)
*t++=*q++;
*t++=10;
}
int scan(){
static int v,j;
v=0,j=1;
while(*s<48)
j=*s++^45;
do
v=v*10+*s++-48;
while(*s>32);
return j?v:-v;
}
template< class T >
void print( register T v){
static int* q=a;
if(!v)*t++=48;
else{
if(v<0)
*t++=45,
v*=-1;
while(v)
*q++=v%10+48,
v/=10;
while(q!=a)
*t++=*--q;
}
*t++=10;
}
}io;
#define read io.scan
#define print io.print
//==========================================================
vector <int> link1[MAXN],link2[MAXN];
int f[MAXN],g[MAXN];
int ind[MAXN],oud[MAXN];
int que[MAXN],head,tail;
inline void topu_1(int now){
head=tail=0;
f[now]=0;
que[tail++]=now;
while(head^tail){
now=que[head++];
for(register int i=0;i<(int)link1[now].size();++i){
int aim=link1[now][i];
--ind[aim];
if(!ind[aim]){
que[tail++]=aim;
}
}
}
for(register int i=0;i<tail;++i){
int x=que[i];
for(register int j=0;j<(int)link1[x].size();++j)
f[link1[x][j]] = max(f[link1[x][j]],f[x]+1);
}
for(register int i=tail-1;~i;--i){
int x=que[i];
for(register int j=0;j<(int)link2[x].size();++j)
g[link2[x][j]] = max(g[link2[x][j]],g[x]+1);
}
}
struct heap{
priority_queue<int> p1,p2;
void add(int x){p1.push(x);}
void del(int x){
p2.push(x);
while((!p1.empty())&&(!p2.empty())&&(p1.top()==p2.top()))
p1.pop(),p2.pop();
}
int max(){return p1.top();}
}pq;
int ans=INF-1,id=INF;
inline void work(){
--tail;
for(register int i=0;i<tail;++i){
int x=que[i];
int kk;
for(register int j=0;j<(int)link2[x].size();++j)
pq.del(kk=f[link2[x][j]]+g[x]);
int tmp=pq.max();
if(ans>tmp) ans=tmp,id=x;
else
if(ans==tmp&&id>x) id=x;
for(register int j=0;j<(int)link1[x].size();++j)
pq.add(kk=f[x]+g[link1[x][j]]);
}
printf("%d %d",id,ans-1);
}
int read_x,read_y;
int main(){
n=read(),m=read();
for(register int i=1;i<=m;++i){
read_x=read(),read_y=read();
link1[read_x].push_back(read_y);
link2[read_y].push_back(read_x);
++ind[read_y],++oud[read_x];
}
pq.p1.push(INF),pq.p2.push(INF);
for(int i=1;i<=n;++i){
link1[S].push_back(i),link2[i].push_back(S),++ind[i],++oud[S];
link1[i].push_back(T),link2[T].push_back(i),++ind[T],++oud[i];
}
topu_1(S);
work();
return 0;
}