T2算答案加成了矩阵的一行然后调了我2个小时
T1:
求图的仅在一个简单环中的边
显然点双
Code:
#include
#define pb push_back
#define fi first
#define se second
using namespace std;
inline int read(){
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
const int N=1000005;
int adj[N],in[N],nxt[N<<1],to[N<<1],cnt=1;
inline void addedge(int u,int v){nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v;}
int dfn[N],low[N],tim,id[N],bcc,num[N],ee[N],ans[N];
int stk[N],top,n,m,vis[N];
pair<int,int> E[N];
vector<int> cir[N];
void dfs(int u,int fa){
dfn[u]=low[u]=++tim;
stk[++top]=u;
for(int e=adj[u];e;e=nxt[e]){
int v=to[e];
if(v==fa)continue;
if(!dfn[v]) dfs(v,u),low[u]=min(low[u],low[v]);
else {low[u]=min(low[u],dfn[v]);continue;}
if(low[v]>=dfn[u]){
int tmp;
bcc++;
do{
tmp=stk[top];
cir[bcc].pb(tmp);
num[bcc]++;
top--;
}while(tmp!=v);
cir[bcc].pb(u);
num[bcc]++;
}
}
}
inline void file(){freopen("graph.in","r",stdin);freopen("graph.out","w",stdout);}
int main(){
n=read(),m=read();
for(int i=1;i<=m;i++){
int u=read(),v=read();
E[i].fi=u,E[i].se=v;
addedge(u,v),addedge(v,u);
}
dfs(1,0);
for(int i=1;i<=bcc;i++){
for(int j=0;j<cir[i].size();j++) id[cir[i][j]]=i;
for(int j=0;j<cir[i].size();j++){
int u=cir[i][j];
for(int e=adj[u];e;e=nxt[e]){
int v=to[e];
if(id[v]==id[u]&&dfn[u]>dfn[v]){ee[i]++;ans[i]^=e>>1;}
}
}
}
int res=0;
for(int i=1;i<=bcc;i++) if(ee[i]==num[i])res^=ans[i];
cout<<res;
return 0;
}
T2:求长度为n的最大价值的串,串中每出现一个给定子串价值会加上一个对应的给定值
串总和200,n规模1e12
显然矩阵快速幂优化AC自动机上DP
Code:
#include
#define pb push_back
#define mp make_pair
#define ll long long
#define fi first
#define se second
#define db double
using namespace std;
inline ll read(){
ll res=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
const int N=205,M=201;
const ll INF=1e18;
int cnt=0;
struct Mat{
ll a[M][M];
inline void init(){
for(int i=0;i<=cnt;++i)
for(int j=0;j<=cnt;++j) a[i][j]=-INF;
}
inline Mat operator * (const Mat &b)const{
Mat res;
res.init();
for(int i=0;i<=cnt;++i)
for(int k=0;k<=cnt;++k) if(a[i][k]!=-INF)
for(int j=0;j<=cnt;++j) if(b.a[k][j]!=-INF)
res.a[i][j]=max(res.a[i][j],a[i][k]+b.a[k][j]);
return res;
}
}trans,bs;
inline Mat ksm(Mat a,ll b){
Mat res=a;
for(;b;b>>=1,a=a*a) if(b&1) res=res*a;
return res;
}
char s[N];
namespace ACAM{
struct trie{
int son[26];
ll val;
}tr[N*10];
inline void ins(int len,ll w){
int now=0;
for(int i=1;i<=len;i++){
if(!tr[now].son[s[i]-'a']) tr[now].son[s[i]-'a']=++cnt;
now=tr[now].son[s[i]-'a'];
}
tr[now].val+=w;
}
int fail[N*10];
inline void buildfail(){
queue<int>q;
for(int i=0;i<26;i++) if(tr[0].son[i]) q.push(tr[0].son[i]);
while(!q.empty()){
int x=q.front();q.pop();
for(int i=0;i<26;i++){
if(tr[x].son[i]) fail[tr[x].son[i]]=tr[fail[x]].son[i],q.push(tr[x].son[i]),tr[tr[x].son[i]].val+=tr[fail[tr[x].son[i]]].val;
else tr[x].son[i]=tr[fail[x]].son[i];
}
}
}
inline void buildmartix(){
for(int i=0;i<=cnt;i++)
for(int j=0;j<26;j++) trans.a[tr[i].son[j]][i]=tr[tr[i].son[j]].val;
}
}
using namespace ACAM;
ll a[N];
inline void file(){freopen("string.in","r",stdin);freopen("string.out","w",stdout);}
int main(){
ll n=read();int m=read();
for(int i=1;i<=m;i++) a[i]=read();
for(int i=1;i<=m;i++){
scanf("%s",s+1);int len=strlen(s+1);
ins(len,a[i]);
}
buildfail();
trans.init();
buildmartix();
trans=ksm(trans,n-1);
ll ans=0;
for(int i=0;i<M;i++) ans=max(ans,trans.a[i][0]);
cout<<ans<<endl;
return 0;
}
T3:有n个位置,某些位置有初始数,再给出m个限制,形如 [ l , r ] [l,r] [l,r]中有k个位置的数严格大于这个区间的其他数,求合法解或者无解,给出的位置总和不超过3e5,位置不超过1e5,限制不超过2e5
显然线段树优化建图+拓扑排序
Code:
#include
#define pb push_back
#define mp make_pair
#define ll long long
#define fi first
#define se second
#define db double
using namespace std;
inline int read(){
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
const int N=5e6+5;
int n;
int p[N<<1],val[N],a[N];
int vis[N<<1],head[N],nxt[N<<1],tot=0,c[N<<1],in[N];
inline void add(int x,int y,int z){in[y]++;vis[++tot]=y;c[tot]=z;nxt[tot]=head[x];head[x]=tot;}
int cnt=0;
inline void build(int k,int l,int r){
if(l==r){p[k]=l;return;}
p[k]=++cnt;
int mid=l+r>>1;
build(k<<1,l,mid),build(k<<1|1,mid+1,r);
add(p[k<<1],p[k],0),add(p[k<<1|1],p[k],0);
}
inline void modify(int k,int l,int r,int ql,int qr,int pos){
if(ql<=l && r<=qr) return add(p[k],pos,1);
int mid=l+r>>1;
if(ql<=mid) modify(k<<1,l,mid,ql,qr,pos);
if(qr>mid) modify(k<<1|1,mid+1,r,ql,qr,pos);
}
bool f=0;
inline bool topsort(){
queue<int>q;
for(int i=1;i<=cnt;i++) if(!in[i]) q.push(i);
while(!q.empty()){
int x=q.front();q.pop();
if(val[x]>1e9 || (a[x] && val[x]>a[x])) return false;
val[x]=max(1,max(val[x],a[x]));
for(int i=head[x];i;i=nxt[i]){
int y=vis[i];
val[y]=max(val[y],val[x]+c[i]);
--in[y];if(in[y]==0) q.push(y);
}
}
for(int i=1;i<=n;i++) if(in[i]) return false;
f=1;return true;
}
int main(){
n=read();cnt=n;int s=read(),m=read();
for(int i=1;i<=s;i++){int x=read();a[x]=read();}
build(1,1,n);
while(m--){
int l=read(),r=read(),k=read();
int last=l-1,inode=++cnt;
for(int i=1;i<=k;i++){
int x=read();
add(inode,x,0);
if(last+1<=x-1) modify(1,1,n,last+1,x-1,inode);
last=x;
}
if(last+1<=r) modify(1,1,n,last+1,r,inode);
}
puts(topsort()?"Possible":"Impossible");
if(f) for(int i=1;i<=n;i++) cout<<val[i]<<" ";
return 0;
}