1.2017广西南宁icpc邀请赛(7/13)
http://acm.hdu.edu.cn/search.php?field=problem&key=2017ACM%2FICPC%B9%E3%CE%F7%D1%FB%C7%EB%C8%FC-%D6%D8%CF%D6%C8%FC%A3%A8%B8%D0%D0%BB%B9%E3%CE%F7%B4%F3%D1%A7%A3%A9&source=1&searchmode=source
A 暴力即可,注意爆ll
B 一共有时间,x,y,颜色四个维度,先开50棵动态开点线段树,维护颜色维度,然后线段树上按照y轴维护每个y坐标上最小的x值,最后按照时间在线回答即可
#include <bits/stdc++.h> #define endl ' ' #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) #define rep(ii,a,b) for(int ii=a;ii<=b;++ii) using namespace std; const int maxn=1e6+10,maxm=2e7+10; int casn,n,m,k; int root[60]; class dsegtree{public: #define nd node[now] #define ndl node[node[now].son[0]] #define ndr node[node[now].son[1]] struct dsegnode{ int son[2],mn; void update(int x){mn=min(mn,x);} }node[maxm]; int cnt; void init(){ memset(root,0,sizeof root); node[0]={0,0,(int)1e9}; cnt=0; } void pushup(int now){nd.mn=min(ndl.mn,ndr.mn);} void update(int pos,int x,int l,int r,int &now){ if(!now) now=++cnt,nd={0,0,x}; if(l==r) {nd.update(x);return ;} if(pos<=(l+r)>>1) update(pos,x,l,(l+r)>>1,nd.son[0]); else update(pos,x,1+((l+r)>>1),r,nd.son[1]); pushup(now); } int query(int s,int t,int l,int r,int now){ if(!now) return 1e9; if(s<=l&&t>=r) return nd.mn; if(t<=(l+r)>>1) return query(s,t,l,(l+r)>>1,nd.son[0]); if(s>(l+r)>>1) return query(s,t,1+((l+r)>>1),r,nd.son[1]); return min(query(s,t,l,(l+r)>>1,nd.son[0]),query(s,t,1+((l+r)>>1),r,nd.son[1])); } }tree; int main() { IO; int a,b,c,d; while(cin>>a){ if(a==3) break; if(a==0) tree.init(); if(a==1||a==2){ cin>>b>>c>>d; if(a==1) tree.update(c,b,1,maxn,root[d]); else { int ans=0; rep(i,0,50)ans+=(tree.query(c,d,1,maxn,root[i])<=b); cout<<ans<<endl; } } } return 0; }
C 三元环计数,答案就是Σ(每个边被三元环包含的次数^2-每个边被三元环包含的次数)/2
#include <bits/stdc++.h> #define endl ' ' #define ll long long #define fi first #define se second #define pii pair<int,int> #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) #define rep(ii,a,b) for(int ii=a;ii<=b;++ii) using namespace std; const int maxn=2e5+10,maxm=2e6+10; //head int casn,n,m,k; vector<pii>g[maxn]; int deg[maxn],a[maxn],b[maxn],cnt[maxn],pos[maxn],v[maxn]; int main() { IO; while(cin>>n>>m){ rep(i,1,n){ g[i].clear(); v[i]=deg[i]=pos[i]=0; } rep(i,1,m){ cin>>a[i]>>b[i]; deg[a[i]]++,deg[b[i]]++; } rep(i,1,m){ cnt[i]=0; if(deg[a[i]]<deg[b[i]])g[a[i]].emplace_back(b[i],i); else if(deg[a[i]]>deg[b[i]])g[b[i]].emplace_back(a[i],i); else { if(a[i]<b[i]) g[a[i]].emplace_back(b[i],i); else g[b[i]].emplace_back(a[i],i); } } rep(i,1,m){ int u=a[i],to=b[i]; for(auto j:g[u]) pos[j.fi]=j.se,v[j.fi]=i+1; for(auto j:g[to]){ int t=j.fi; if(v[t]==i+1){ cnt[i]++; cnt[pos[t]]++; cnt[j.se]++; } } } ll ans=0; rep(i,1,m) ans+=1ll*cnt[i]*(cnt[i]-1)/2; cout<<ans<<endl; } return 0; }
D 递推+矩阵快速幂,记录一下完全体的矩阵板子
#include <bits/stdc++.h> #define endl ' ' #define ll long long #define pii pair<int,int> #define all(x) x.begin(),x.end() #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) #define rep(ii,a,b) for(int ii=a;ii<=b;++ii) using namespace std; const int maxn=1e6+10,maxm=2e6+10; const ll mod=1e9+7; ll n,m,casn,q,k; class matrix{public://带取模 int a,b; vector<vector<ll> > x; matrix(int a=1,int b=1){//行数,列数,初始均为0 this->a=a,this->b=b; x.resize(a); for(auto &i:x){i.resize(b);std::fill(all(i),0);} } void e(int n){a=b=n;x=matrix(n,n).x;for(int i=0;i<n;i++)x[i][i]=1;}//n*n的单位矩阵 void fill(ll xx=0){for(int i=0;i<a;i++)for(int j=0;j<b;j++)x[i][j]=xx;} //全部填为xx void fill(vector<vector<ll>> &y){x=y;a=y.size();b=y[0].size();}//用二维数组填充 matrix operator *(matrix &m){ matrix ans(a,m.b); for(int i=0;i<a;i++)for(int j=0;j<m.b;j++)for(int k=0;k<b;k++)if(x[i][k]&&m.x[k][j]) ans.x[i][j]=(mod+ans.x[i][j]+(x[i][k]*m.x[k][j]+mod)%mod)%mod; return ans; } matrix operator +(matrix &m){ matrix ans(a,m.b); for(int i=0;i<a;i++)for(int j=0;j<b;j++)ans.x[i][j]=(x[i][j]+m.x[i][j]+mod)%mod; return ans; } matrix operator -(matrix &m){ matrix ans(a,m.b); for(int i=0;i<a;i++)for(int j=0;j<b;j++)ans.x[i][j]=(x[i][j]-m.x[i][j]+mod)%mod; return ans; } matrix pow(ll p){//快速幂 matrix ans;ans.e(a);matrix t;t.fill(x); while(p){if(p&1) ans=t*ans;t=t*t;p>>=1;}return ans; } }; const ll ff[4][4]={1,1,0,0,5,0,1,0,1,0,0,1,-1,0,0,0}; const ll fc[4]={1,5,11,36}; int main() { IO; vector<vector<ll> > f0(4,vector<ll>(4,0)),f1(1,vector<ll>(4,0)); rep(i,0,3){ rep(j,0,3) f0[i][j]=ff[i][j]; f1[0][i]=fc[3-i]; } while(cin>>n){ if(n<=4) { cout<<fc[n-1]<<endl; continue; } matrix ans; ans.fill(f1); matrix c; c.fill(f0); c=c.pow(n-4); ans=ans*c; cout<<ans.x[0][0]<<endl; } }
E 前缀+后缀即可,注意边界
G 贪心,先拿走所有2个以上的部分,然后连续三个的优先级为:112 > 2XX > 111
J dfs序+01字典树,可以离线也可以持久化
离线:
#include <bits/stdc++.h> #define endl ' ' #define all(x) x.begin(),x.end() #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) #define rep(ii,a,b) for(int ii=a;ii<=b;++ii) using namespace std; const int maxn=1e5+10,maxm=2e6+10; //head int casn,n,m,k; vector<int> g[maxn]; class trie{public: int node[maxn*40][3],top; void init(){memset(node[0],0,sizeof (node[0]));top=1;} void add(int x,int id){ int now,nx,rt,t; for(rt=0,t=31;~t;rt=nx,--t){ nx=node[rt][now=x>>t&1]; if(!nx) memset(node[top],0,sizeof (node[top])),node[rt][now]=nx=top++; node[nx][2]=id; } } int query(int x,int l){ int rt,nx,now,t,ans=0; for(rt=0,t=31;~t;rt=nx,--t){ now=x>>t&1,ans<<=1; if((nx=node[rt][!now])&&node[nx][2]<=l)ans+=1; else nx=node[rt][now]; } return ans; } }tree; struct node{ int id,x,l,r; bool operator<(node &n)const {return l>n.l;} }ask[maxn]; int in[maxn],out[maxn],id[maxn]; int cnt,val[maxn],ans[maxn]; void dfs(int now){ in[now]=++cnt;id[cnt]=now; for(auto i:g[now]) dfs(i); out[now]=cnt; } int main() { IO; while(cin>>n>>k){ cnt=0; tree.init(); rep(i,1,n) g[i].clear(); rep(i,1,n) cin>>val[i]; rep(i,2,n){ int x;cin>>x; g[x].push_back(i); } dfs(1); rep(i,1,k){ int a,b;cin>>a>>b; ask[i]={i,b,in[a],out[a]}; } sort(ask+1,ask+1+k); int pos=n; rep(i,1,k){ while(pos>=ask[i].l) tree.add(val[id[pos]],pos),--pos; ans[ask[i].id]=tree.query(ask[i].x,ask[i].r); } rep(i,1,k) cout<<ans[i]<<endl; } return 0; }
持久化字典树
#include <bits/stdc++.h> #define endl ' ' #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) #define rep(ii,a,b) for(int ii=a;ii<=b;++ii) using namespace std; const int maxn=1e5+10,maxm=2e6+10; //head int casn,n,m,k; int rt[maxn]; vector<int> g[maxn]; class ptrie{public: int node[maxn*40][2],top; void init(){rt[0]=node[0][1]=node[0][0]=top=0;} int add(int pre,int val,int bit=31){ int now=++top; if(bit<0) return now; int t=val>>bit&1; node[now][t]=add(node[pre][t],val,bit-1); node[now][t^1]=node[pre][t^1]; return now; } int query(int now,int pre,int val,int bit=31,int ans=0){ if(bit<0) return ans; int t=val>>bit&1; if(node[now][t^1]-node[pre][t^1]>0) return query(node[now][t^1],node[pre][t^1],val,bit-1,ans|(1<<bit)); return query(node[now][t],node[pre][t],val,bit-1,ans); } }tree; int in[maxn],out[maxn]; int cnt,val[maxn]; void dfs(int now){ in[now]=++cnt; rt[cnt]=tree.add(rt[cnt-1],val[now]); for(auto i:g[now]) dfs(i); out[now]=cnt; } int main() { IO; while(cin>>n>>k){ cnt=0; tree.init(); rep(i,1,n) g[i].clear(); rep(i,1,n) cin>>val[i]; rep(i,2,n){ int x;cin>>x; g[x].push_back(i); } dfs(1); rep(i,1,k){ int a,b;cin>>a>>b; cout<<tree.query(rt[out[a]],rt[in[a]-1],b)<<endl; } } return 0; }
2