zoukankan      html  css  js  c++  java
  • HEOI2016 题解

    HEOI2016 题解

    • Q:为什么要在sdoi前做去年的heoi题
    • A:我省选药丸

    http://cogs.pro/cogs/problem/index.php?key=heoi2016

    D1T1 树

    树剖直接做

    或者操作逆序,并查集维护自己和祖先中第一个打标记的点,注意1号点本身有标记,mark[1]++

    代码在最后

    D1T2排序

    计数排序拿80...

    二分答案,(ge)设为1,(<)设为0,排序就可以用线段树模拟了. 鏼鏼鏼!

    代码还没写

    D1T3序列

    md一开始看错题了

    写出(O(n^2))的DP,发现裸三维偏序啊,(j<i, max_j < a_i, a_j < min_i)

    注意最后调用cdq(mid+1, r)前按id排一下序

    cdq真是太棒了!

    代码在最后

    D2T1游戏

    二分图匹配...

    硬石头把一行拆成了好几个点...

    代码在最后

    D2T2求和

    以前做了

    D2T3字符串

    题意:多次询问(S[a,b])的所有子串与(S[c,d])的LCP

    40分(O(n^2))暴力 每次重构sam

    一开始想的是,反转后建sam,建出Parent Tree,往上找第一个Right集合中有[a,b]的节点。问题在于限制了在[a,b]范围内,不一定是越深的祖先越好因为到b就截断了

    考虑二分lcp长度,那么变成了判断Right有没有[a+len-1, b]范围内的点(注意我反转了字符串)

    这样就可以倍增了,判断可以对dfs序建主席树权值是后缀

    但这样是三个log

    其实等价于我们先倍增到val>=len的最浅的点,看看Right集合里有没有,这样就是两个log了

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    const int N=1e5+5;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    int n, Q, fa[N], u, v, f[N], ans[N], m, mark[N];
    int find(int x) {return x==fa[x] ? x : fa[x]=find(fa[x]);}
    struct meow{char s[5]; int x, id;} q[N];
    
    struct edge{int v, ne;} e[N];
    int cnt=1, h[N];
    inline void ins(int u, int v) {e[++cnt]=(edge){v, h[u]}; h[u]=cnt;}
    namespace graph {
    	int q[N], head, tail;
    	void bfs() {
    		head=tail=1;
    		q[tail++]=1;
    		while(head != tail) {
    			int u=q[head++];
    			if(!fa[u]) fa[u] = find(f[u]);
    			for(int i=h[u];i;i=e[i].ne) q[tail++] = e[i].v;
    		}
    	}
    }
    
    int main() {
    	//freopen("in","r",stdin);
    	freopen("heoi2016_tree.in","r",stdin);
    	freopen("heoi2016_tree.out","w",stdout);
    	n=read(); Q=read();
    	fa[1]=1; mark[1]++;
    	for(int i=1; i<n; i++) u=read(), v=read(), f[v]=u, ins(u, v);
    	for(int i=1; i<=Q; i++) {
    		scanf("%s", q[i].s), q[i].x=read();
    		if(q[i].s[0] == 'C') fa[ q[i].x ] = q[i].x, mark[ q[i].x ]++;
    		else q[i].id=++m;
    	}
    	graph::bfs();
    	for(int i=Q; i>=1; i--) {
    		if(q[i].s[0] == 'C') {
    			mark[ q[i].x ]--;
    			if(!mark[ q[i].x ]) fa[ q[i].x ] = find(f[q[i].x]);
    		}else ans[q[i].id] = find(q[i].x);
    	}
    	for(int i=1; i<=m; i++) printf("%d
    ", ans[i]);
    }
    
    
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    const int N=1e5+5;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    int n, Q, x, y, f[N];
    struct meow{int a, b, c, id;} a[N]; //max --> b, min --> c;
    inline bool cmpb(const meow &a, const meow &b) {return a.b < b.b;}
    inline bool cmpa(const meow &a, const meow &b) {return a.a < b.a;}
    inline bool cmpid(const meow &a, const meow &b) {return a.id < b.id;}
    namespace bit {
    	int n, c[N], t[N], T;
    	inline void ini() {T++; }
    	inline void upd(int p, int v) { //printf("upd %d %d
    ",p,v);
    		for(; p<=n; p+=p&-p) {
    			if(t[p] != T) t[p]=T, c[p]=v;
    			else if(c[p] < v) c[p]=v;
    		}
    	}
    	inline int max(int p) { //printf("max %d
    ",p);
    		int ans=0;
    		for(; p; p-=p&-p) if(t[p] == T && c[p] > ans) ans = c[p];
    		return ans;
    	}
    }
    void cdq(int l, int r) { //printf("
    -------cdq %d %d
    ",l,r);
    	if(l==r) return;
    	int mid=(l+r)>>1;
    	cdq(l, mid);
    
    	sort(a+l, a+mid+1, cmpb); sort(a+mid+1, a+r+1, cmpa);
    	bit::ini();
    	int p1=l, p2=mid+1;
    	while(p1 <= mid || p2 <= r) {
    		if(p2 > r || (p1 <= mid && a[p1].b <= a[p2].a) ) bit::upd(a[p1].a, f[a[p1].id]), p1++;
    		else f[a[p2].id] = max(f[a[p2].id], bit::max(a[p2].c)+1), p2++; //printf("p2  %d  %d %d
    ", p2, a[p2].id, f[a[p2].id]),p2++;
    	}
    
    	sort(a+mid+1, a+r+1, cmpid);
    	cdq(mid+1, r);
    }
    int main() {
    	//freopen("in","r",stdin);
    	freopen("heoi2016_seq.in","r",stdin);
    	freopen("heoi2016_seq.out","w",stdout);
    	n=read(); Q=read();
    	for(int i=1; i<=n; i++) x=read(), a[i]=(meow){x, x, x, i}, f[i]=1, bit::n = max(bit::n, x);
    	for(int i=1; i<=Q; i++) x=read(), y=read(), a[x].b = max(a[x].b, y), a[x].c = min(a[x].c, y), bit::n = max(bit::n, y);
    	cdq(1, n);
    	int ans=0;
    	for(int i=1; i<=n; i++) ans = max(ans, f[i]);// printf("%d ",f[i]); puts(" f");
    	printf("%d", ans);
    }
    
    
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    const int N=5100, M=1e5+5, INF=1e9+5;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    int n, m, s, t, X, Y, idx[55][55], idy[55][55]; 
    char str[55][55];
    namespace mf {
    	struct edge{int v, ne, c, f;}e[M];
    	int cnt=1, h[N];
    	inline void ins(int u, int v, int c) {
    		e[++cnt]=(edge){v, h[u], c, 0}; h[u]=cnt;
    		e[++cnt]=(edge){u, h[v], 0, 0}; h[v]=cnt;
    	}
    	int q[N], head, tail, d[N], vis[N];
    	bool bfs() {
    		memset(vis, 0, sizeof(vis));
    		head=tail=1;
    		q[tail++]=s; d[s]=0; vis[s]=1;
    		while(head != tail) {
    			int u=q[head++];
    			for(int i=h[u];i;i=e[i].ne) 
    				if(!vis[e[i].v] && e[i].c>e[i].f) {
    					vis[e[i].v]=1; 
    					d[e[i].v] = d[u]+1;
    					q[tail++]=e[i].v;
    					if(e[i].v == t) return true;
    				}
    		}
    		return false;
    	}
    	int cur[N];
    	int dfs(int u, int a) {
    		if(u==t || a==0) return a;
    		int flow=0, f;
    		for(int &i=cur[u];i;i=e[i].ne) 
    			if(d[e[i].v] == d[u]+1 && (f = dfs(e[i].v, min(a, e[i].c-e[i].f)) )>0) {
    				flow += f;
    				e[i].f += f;
    				e[i^1].f -= f;
    				a -= f;
    				if(a==0) break;
    			}
    		if(a) d[u]=-1;
    		return flow;
    	}
    	int dinic() {
    		int flow=0;
    		while(bfs()) {
    			for(int i=s; i<=t; i++) cur[i]=h[i];
    			flow += dfs(s, INF);
    		}
    		return flow;
    	}
    
    	int g[N][N];
    	void build() {
    		for(int i=1; i<=n; i++) {
    			X++; 
    			for(int j=1; j<=m; j++) if(str[i][j] == '#') X++;
    			else idx[i][j] = X;
    		}
    		Y=X;
    		for(int j=1; j<=m; j++) {
    			Y++;
    			for(int i=1; i<=n; i++) if(str[i][j] == '#') Y++;
    			else idy[i][j] = Y;
    		}
    		s=0; t=Y+1;
    
    		//for(int i=1; i<=n; i++) for(int j=1; j<=m; j++) printf("idx %d %d   %d
    ",i,j,idx[i][j]);
    		//for(int j=1; j<=m; j++) for(int i=1; i<=n; i++) printf("idy %d %d   %d
    ",i,j,idy[i][j]);
    		int has[N];
    		for(int i=1; i<=n; i++) 
    			for(int j=1; j<=m; j++) if(str[i][j] == '*') 
    				ins(idx[i][j], idy[i][j], 1), has[idx[i][j]]=1, has[idy[i][j]]=1;
    		for(int i=1; i<=X; i++) if(has[i]) ins(s, i, 1);
    		for(int i=X+1; i<=Y; i++) if(has[i]) ins(i, t, 1);
    	}
    }
    
    int main() {
    	//freopen("in","r",stdin);
    	//freopen("heoi2016_game.in","r",stdin);
    	//freopen("heoi2016_game.out","w",stdout);
    	n=read(); m=read(); 
    	for(int i=1; i<=n; i++) scanf("%s",str[i]+1);
    	mf::build();
    	int ans = mf::dinic();
    	printf("%d", ans);
    }
    
    
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    #define lc(x) t[x].l
    #define rc(x) t[x].r
    const int N=2e5+5;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    int n, Q, pos[N], a, b, c, d; 
    char s[N];
    namespace sam {
    	struct meow{int ch[26], par, val;}t[N];
    	int sz=1, last=1, root=1;
    	int ri[N], suf[N];
    	inline void extend(int c, int id) {
    		int p=last, np=++sz; t[np].val = t[p].val+1; 
    		pos[id] = np; suf[np] = id; //printf("id %d %d
    ",id,np);
    		for(; p && !t[p].ch[c]; p=t[p].par) t[p].ch[c]=np;
    		if(!p) t[np].par = root;
    		else {
    			int q = t[p].ch[c];
    			if(t[q].val == t[p].val+1) t[np].par = q;
    			else {
    				int nq=++sz; t[nq]=t[q]; t[nq].val = t[p].val+1;
    				t[q].par = t[np].par = nq;
    				for(; p && t[p].ch[c]==q; p=t[p].par) t[p].ch[c]=nq;
    			}
    		}
    		last=np;
    	}
    } using sam::suf; using sam::extend;
    
    namespace tr {
    	struct edge{int v, ne;} e[N];
    	int cnt=1, h[N];
    	inline void ins(int u, int v) { //printf("ins %d %d
    ",u,v);
    		e[++cnt]=(edge){v, h[u]}; h[u]=cnt;}
    
    	struct meow{int l, r, size;} t[N*20];
    	int sz=0, root[N];
    	inline void insert(int &x, int l, int r, int p) {
    		t[++sz]=t[x]; x=sz;
    		t[x].size++;
    		if(l==r) return;
    		int mid=(l+r)>>1;
    		if(p<=mid) insert(lc(x), l, mid, p);
    		else insert(rc(x), mid+1, r, p);
    	}
    	inline bool exist(int x, int y, int l, int r, int ql, int qr) {
    		if(ql<=l && r<=qr) return t[y].size - t[x].size > 0;
    		if(t[y].size - t[x].size == 0) return 0;
    		int mid = (l+r)>>1, ans=0;
    		if(ql<=mid) ans |= exist(lc(x), lc(y), l, mid, ql, qr);
    		if(mid<qr ) ans |= exist(rc(x), rc(y), mid+1, r, ql, qr);
    		return ans;
    	}
    
    	int fa[N][20], deep[N], L[N], R[N], dfc, ver[N]; // dfc = sam::sz
    	int tot;
    	void dfs(int u) {
    		L[u]=++dfc; ver[dfc]=u;
    		for(int i=1; (1<<i)<=deep[u]; i++)
    			fa[u][i] = fa[ fa[u][i-1] ][i-1];
    		for(int i=h[u];i;i=e[i].ne)
    			if(e[i].v != fa[u][0]) {
    				fa[e[i].v][0] = u;
    				deep[e[i].v] = deep[u]+1;
    				dfs(e[i].v);
    			}
    		R[u]=dfc;
    	}
    
    	void build() {
    		//for(int i=1; i<=dfc; i++) printf("%d ",ver[i]); puts("");
    		//for(int i=1; i<=dfc; i++) printf("lr %d %d %d 
    ",i,L[i],R[i]);
    		//for(int i=2; i<=dfc; i++) printf("val %d %d
    ",i,sam::t[i].val);
    		for(int i=1; i<=dfc; i++) {
    			root[i] = root[i-1];
    			int u=ver[i];
    			if(suf[u]) insert(root[i], 1, n, suf[u]);// printf("suf %d --> %d --> %d
    ", i, u, suf[u]);
    		}
    	}
    	bool check(int len, int l, int r, int x) { //printf("check %d  [%d, %d]  %d
    ", len, l, r, x);
    		using sam::t;
    		for(int i=17; i>=0; i--) 
    			if(fa[x][i] && t[ fa[x][i] ].val >= len) x=fa[x][i];
    		//printf("x %d  %d  L %d R %d
    ",x, t[x].val, L[x], R[x]);
    		return exist(root[L[x]], root[R[x]], 1, n, l, r);
    	}
    	void solve(int a, int b, int c, int d) { //printf("
    solve %d %d  %d %d
    ",a,b,c,d);
    		int l=0, r=min(d-c+1, b-a+1), ans=-1;
    		while(l<=r) {
    			int mid=(l+r)>>1;
    			if(check(mid, a+mid-1, b, pos[d])) ans=mid, l=mid+1;
    			else r=mid-1;
    		}
    		printf("%d
    ", ans);
    	}
    }
    
    int main() {
    	//freopen("in","r",stdin);
    	//freopen("heoi2016_str.in","r",stdin);
    	//freopen("heoi2016_str.out","w",stdout);
    	n=read(); Q=read(); scanf("%s", s+1);
    	reverse(s+1, s+1+n);
    	for(int i=1; i<=n; i++) extend(s[i]-'a', i);
    	for(int i=2; i<= sam::sz; i++) tr::ins(sam::t[i].par, i);
    	tr::dfs(1); tr::build();
    	
    	for(int i=1; i<=Q; i++) {
    		a=n-read()+1; b=n-read()+1; c=n-read()+1; d=n-read()+1;
    		swap(a, b); swap(c, d);
    		tr::solve(a, b, c, d);
    	}
    }
    
    

    sort的80分暴力

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    const int N=2e5+5;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    int n, Q, x, op, l, r, t1[N], t2[N];
    int *a = t1, *b = t2;
    int c[N], SIZE;
    void csort(int *a, int m) { 
    	memset(c, 0, SIZE);
    	for(register int i=1; i<=m; i++) c[a[i]]++;// printf("%d ",a[i]); puts(" sort");
    	for(register int i=1; i<=n; i++) c[i] += c[i-1];
    	for(register int i=1; i<=m; i++) b[c[a[i]]--] = a[i];
    	for(register int i=1; i<=m; i++) a[i]=b[i];// printf("b %d %d
    ",i,b[i]);
    }
    void rever(int l, int r) { while(l<r) swap(a[l++], a[r--]); }
    int main() {
    	//freopen("in","r",stdin);
    	freopen("heoi2016_sort.in","r",stdin);
    	freopen("heoi2016_sort.out","w",stdout);
    	n=read(); Q=read(); SIZE = sizeof(int)*(n+1);
    	for(int i=1; i<=n; i++) a[i]=read();
    	for(int i=1; i<=Q; i++) {
    		op=read(); l=read(); r=read();
    		csort(a+l-1, r-l+1);
    		if(op==1) rever(l, r);
    		//for(int i=1; i<=n; i++) printf("%d ", a[i]); puts("");
    	}
    	printf("%d", a[read()]);
    }
    
    
  • 相关阅读:
    智能推荐算法演变及学习笔记(三):CTR预估模型综述
    从中国农业银行“雅典娜杯”数据挖掘大赛看金融行业数据分析与建模方法
    智能推荐算法演变及学习笔记(二):基于图模型的智能推荐(含知识图谱/图神经网络)
    (设计模式专题3)模板方法模式
    (设计模式专题2)策略模式
    (设计模式专题1)为什么要使用设计模式?
    关于macOS上常用操作命令(持续更新)
    记录下关于RabbitMQ常用知识点(持续更新)
    EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.
    SpringCloud教程二:Ribbon(Finchley版)
  • 原文地址:https://www.cnblogs.com/candy99/p/6675548.html
Copyright © 2011-2022 走看看