zoukankan      html  css  js  c++  java
  • test20190829

    闲扯

    我上当了。。

    明明是 (NOI) 模拟题,结果被标题改成 (NOIP) 来给我们考??

    (T3) 圆环面积并,这谁顶得住啊。。。。

    题面

    题面

    (T1)

    Solution

    对每个点为起点跑一次最短路,构造出相对应的最短路径图。可以发现这是一个 (DAG)

    对于每一条边的答案,它在当前图中的贡献值为 (num_u*cnt_v) 。其中 (u) 为起点, (v) 为终点, (num) 表示到该点的最短路个数, (cnt) 表示这个点能到达的点数。

    每次 (DFS) 统计以上内容。因为是 (DAG) ,所以最短路个数可以用拓扑排序求出,其他的 (DFS) 维护即可。

    Code

    #include<bits/stdc++.h>
    #define del(a,i) memset(a,i,sizeof(a))
    #define ll long long
    #define inl inline
    #define il inl void
    #define it inl int
    #define ill inl ll
    #define re register
    #define ri re int
    #define rl re ll
    #define mid ((l+r)>>1)
    #define lowbit(x) (x&(-x))
    #define INF 0x3f3f3f3f
    using namespace std;
    template<class T>il read(T &x){
    	int f=1;char k=getchar();x=0;
    	for(;k>'9'||k<'0';k=getchar()) if(k=='-') f=-1;
    	for(;k>='0'&&k<='9';k=getchar()) x=(x<<3)+(x<<1)+k-'0';
    	x*=f;
    }
    template<class T>il print(T x){
    	if(x/10) print(x/10);
    	putchar(x%10+'0');
    }
    ll mul(ll a,ll b,ll mod){long double c=1.;return (a*b-(ll)(c*a*b/mod)*mod)%mod;}
    it qpow(int x,int m,int mod){
    	int res=1,bas=x%mod;
    	while(m){
    		if(m&1) res=(res*bas)%mod;
    		bas=(bas*bas)%mod,m>>=1;
    	}
    	return res%mod;
    }
    const int MAXN = 15e2 + 5,mod = 1e9+7;
    int n,m,u,v,d,ans[5005],dis[MAXN],head[MAXN],num_edge,hd[MAXN],num,cnt[MAXN],du[MAXN],ru[MAXN];
    struct Edge{
    	int next,to,dis,id;
    	Edge(){}
    	Edge(int next,int to,int dis,int id):next(next),to(to),dis(dis),id(id){}
    }edge[5005],ed[5005];
    il add_edge(int u,int v,int dis,int id){edge[++num_edge]=Edge(head[u],v,dis,id),head[u]=num_edge;}
    bool tr[MAXN];
    il dijkstra(int s){
    	del(tr,0),del(dis,0x3f),dis[s]=0;
    	priority_queue<pair<int,int> > q;q.push(make_pair(0,s));
    	while(!q.empty()){
    		pair<int,int> tmp=q.top();q.pop();
    		ri pos=tmp.second;
    		if(tr[pos]) continue;
    		tr[pos]=1;
    		for(ri i=head[pos];i;i=edge[i].next){
    			if(dis[edge[i].to]>dis[pos]+edge[i].dis){
    				dis[edge[i].to]=dis[pos]+edge[i].dis;
    				if(!tr[edge[i].to]) q.push(make_pair(-dis[edge[i].to],edge[i].to));
    			}
    		}
    	}
    }
    il DFS(int u){
    	for(ri i=hd[u];i;i=ed[i].next){
    		du[ed[i].to]=(du[ed[i].to]+du[u])%mod;
    		ru[ed[i].to]--;
    		if(!ru[ed[i].to]) DFS(ed[i].to);
    	}
    }
    il DFS1(int u){
    	tr[u]=1;
    	for(ri i=head[u];i;i=edge[i].next)
    		if(dis[u]+edge[i].dis==dis[edge[i].to]){
    			ed[++num]=Edge(hd[u],edge[i].to,edge[i].dis,edge[i].id),hd[u]=num;
    			ru[edge[i].to]++;
    			if(!tr[edge[i].to]) DFS1(edge[i].to);
    		}
    }
    il DFS2(int u){
    	cnt[u]=1,tr[u]=1;
    	for(ri i=hd[u];i;i=ed[i].next){
    		if(!tr[ed[i].to]) DFS2(ed[i].to);
    		cnt[u]+=cnt[ed[i].to];
    	}
    }
    il DFS3(int u){
    	tr[u]=1;
    	for(ri i=hd[u];i;i=ed[i].next){
    		ans[ed[i].id]=(ans[ed[i].id]+du[u]*cnt[ed[i].to])%mod;
    		if(tr[ed[i].to]) continue;
    		DFS3(ed[i].to);
    	}
    }
    il solve(int u){
    	num=0,del(hd,0),del(cnt,0),del(du,0),del(ru,0),du[u]=1;
    	dijkstra(u),del(tr,0);
    	DFS1(u),del(tr,0);
    	DFS(u),del(tr,0);
    	DFS2(u),del(tr,0);
    	DFS3(u);
    }
    int main()
    {
    	freopen("path.in","r",stdin);
    	freopen("path.out","w",stdout);
    	read(n),read(m);
    	for(ri i=1;i<=m;++i) read(u),read(v),read(d),add_edge(u,v,d,i);
    	for(ri i=1;i<=n;++i) solve(i);
    	for(ri i=1;i<=m;++i) print(ans[i]),puts("");
    	return 0;
    }
    

    (T2)

    Solution

    暴力AC

    分块,每次查询时,找到向右第一个大于 (val_i) 的值,再次之前所有的 (j) 都可以满足要求。

    对于剩下的部分,可以发现答案是单调不降的,可以用单调栈维护。

    第一个块暴力处理。

    处理完当前块之后,二分查找下一个块中第一个不小于当前最大值的位置,然后依次进行处理。

    对于修改时直接暴力重构当前区间的单调栈即可。

    Code

    #include<bits/stdc++.h>
    using namespace std;
    template<class T> T read(){
    	T x=0,w=1;char c=getchar();
    	for(;!isdigit(c);c=getchar())if(c=='-') w=-w; 
    	for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    	return x*w;
    }
    template<class T> T read(T&x){
    	return x=read<T>();
    }
    #define co const
    #define il inline
    typedef long long LL;
    
    co int N=50000+10,B=883+10,M=56+10;
    int A[N],bel[N];
    int L[M],R[M],st[M][B],top[M];
    
    void change(int l,int r,int st[],int&top){
    	top=0;
    	for(int i=r;i>=l;--i){
    		while(top&&A[st[top]]<A[i]) --top;
    		st[++top]=i;
    	}
    }
    int query(int p,int num){
    	int ans=0;
    	int bl=bel[p],mx=A[p];
    	for(int i=p+1;i<=R[bl];++i){
    		mx=max(mx,A[i]);
    		if(mx<=max(A[p],A[i])) ++ans;
    	}
    	for(int i=bl+1;i<=num;++i){
    		int l=0,r=top[i];
    		if(mx==A[p]){
    			while(l<r){
    				int mid=(l+r+1)>>1;
    				if(A[st[i][mid]]>mx) l=mid;
    				else r=mid-1;
    			}
    			if(l==0) ans+=R[i]-L[i]+1;
    			else{
    				ans+=st[i][l]-1-L[i]+1;
    				ans+=l-1+1;
    			}
    		}
    		else{
    			while(l<r){
    				int mid=(l+r+1)>>1;
    				if(A[st[i][mid]]>=mx) l=mid;
    				else r=mid-1;
    			}
    			ans+=l-1+1;
    		}
    		mx=max(mx,A[st[i][1]]);
    	}
    	return ans;
    }
    int main(){
    	freopen("seq.in","r",stdin),freopen("seq.out","w",stdout);
    	int n=read<int>(),m=read<int>();
    	int siz=sqrt(n*log2(n)),num=(n+siz-1)/siz;
    	for(int i=1;i<=n;++i) read(A[i]),bel[i]=(i+siz-1)/siz;
    	for(int i=1;i<=num;++i){
    		L[i]=R[i-1]+1,R[i]=min(i*siz,n);
    		change(L[i],R[i],st[i],top[i]);
    	}
    	for(char opt[2];m--;){
    		scanf("%s",opt);
    		if(opt[0]=='C'){
    			int p=read<int>();
    			A[p]=read<int>();
    			int bl=bel[p];
    			change(L[bl],R[bl],st[bl],top[bl]);
    		}
    		else printf("%d
    ",query(read<int>(),num));
    	}
    	return 0;
    }
    

    (T3)

    咕咕咕

    总结

    输入时最好不要用 (scanf("\%c")) ,好像很容易炸的样子。

    对于不会的题要多思考,找到它的特殊性质,从这方面入手。

    还有对数据范围要敏感,看到 (50000) 应该想到分块、莫队好像也是用的分块等。

  • 相关阅读:
    AutoComplete控件
    META httpequiv 大全
    十四条必知的手机电池充电技巧
    什么是套接字
    理解HTTP session原理及应用
    Adodb.Stream取得图像的高宽
    微软Windows 7测试版下载网上泄露
    Oracle新手學習
    Oracle字符串函数
    Oracle的Window服务启动时并不启动实例
  • 原文地址:https://www.cnblogs.com/TheShadow/p/11430758.html
Copyright © 2011-2022 走看看