T1 u:c++
一看到修改這麼多,但詢問其實只有一個不難想到差分,可是他這個形狀能夠說很不規則,因而咱們想到分別維護豎着的和斜着的差分,而後最後合併便可。ide
考場上瞎調了一波係數莫名AC,實際上是維護差分的差分。ui
考試時發現對拍暴力輸不出來東西時,慌的不行,對拍的數據範圍必定要搞對。spa
1 //weihu xiezhede chafen? 2 //對於每一個知足 x ∈ [r, r +l), y ∈ [c, x−r +c] 3 //的元素 (x, y),將權值增長 s。 4 #include<bits/stdc++.h> 5 using namespace std; 6 #define int long long 7 #define sc(x) printf("%lld\n",x) 8 const int N=1e3+10; 9 int cf[N][N],cf1[N][N],n,q,a[N][N]; 10 signed main(){ 11 //freopen("data.in","r",stdin); 12 //freopen("my.out","w",stdout); 13 scanf("%lld%lld",&n,&q); 14 if(!q){puts("0");return 0;} 15 for(int i=1;i<=q;++i){ 16 int r,c,l,s; 17 scanf("%lld%lld%lld%lld",&r,&c,&l,&s); 18 cf[r][c]+=s; 19 cf1[r][c+1]+=s; 20 if(r+l<=n) cf[r+l][c]-=s; 21 if(r+l<=n&&c+l+1<=n) cf1[r+l][c+l+1]-=s; 22 } 23 for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) cf[i][j]+=cf[i-1][j]; 24 for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) cf1[i][j]+=cf1[i-1][j-1]; 25 int ans=0; 26 for(int i=1;i<=n;++i){ 27 for(int j=1;j<=n;++j){ 28 cf[i][j]-=cf1[i][j]; 29 } 30 } 31 // ans=cf[1][1]; 32 for(int i=1;i<=n;++i){ 33 for(int j=1;j<=n;++j){ 34 cf[i][j]+=cf[i][j-1]; 35 //cout<<cf[i][j]<<" "; 36 ans^=cf[i][j]; 37 } 38 //cout<<endl; 39 } 40 sc(ans); 41 }
T2 v:code
考場上想狀壓,可是發現數據範圍稍大,可能過不了,而後也沒什麼思路。blog
正解 記憶化搜索+hash_map,實際上是和裸狀壓同樣的,可是加了記憶化加速,比較難搞的一點就是如何把刪了一個球后的狀態用二進制表示出來,有點繞。ci
還有就是,hash_map不能僅僅記錄狀態,還要記錄當前所剩的球數,由於000110和000110對於狀態來講是同樣的,可是前面的黑球數是不必定的,這樣保證狀態惟一。因此hash_map有點難搞,%%%DeepinC重載中括號取地址hash_map,由於本身是實在是不會hash_map,因此就沒臉得照着DeepinC神的hash_map打了。hash
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=35; 4 #define signed long long 5 const int M=3e7+10; 6 char s[N]; 7 int n,k,a[N]; 8 struct hash_map{//hash_map shizhaozhe DeepinC dedade zhendebuhui hash_map 9 int first[30000017],nex[M],to[M],tot;short l[M],len; 10 double val[M]; 11 double &operator[] (const register int st){ 12 signed f=st*1ll*len%30000017; 13 for(register int i=first[f];i;i=nex[i]) if(to[i]==st&&l[i]==len) return val[i]; 14 to[++tot]=st,nex[tot]=first[f],first[f]=tot,l[tot]=len; val[tot]=-1;return val[tot]; 15 } 16 }mp; 17 inline double max(const register double a,const register double b){ 18 return a>b?a:b; 19 } 20 21 double dfs(const register int l,const register int st){//cout<<l<<" "<<st<<endl; 22 if(l==n-k) return 0.0; 23 mp.len=l;//meicichongxinfuzhi,yinwei zhuangtaihechangdushiduiyingde 24 if(mp[st]>-0.1) return mp[st]; 25 mp[st]=0; 26 short sta[N],jk=l+1,kh=(l>>1)+1; 27 for(register int i=1;i^jk;++i) sta[i]=(st>>i-1)&1; 28 // reverse(sta+1,sta+l+1); 29 // for(int i=1;i<=l;++i) cout<<sta[i]<<" ";cout<<endl; 30 31 for(register int i=1;i^kh;++i){ 32 short h=l-i+1; 33 int state1=st>>l-i+1<<l-i|st&(1<<l-i)-1,state2=st>>l-h+1<<l-h|st&(1<<l-h)-1; 34 // cout<<st<<" "<<l<<" "<<i<<endl; 35 // cout<<state1<<" "<<state2<<endl; 36 double ans1=dfs(l-1,state1)+sta[h],ans2=dfs(l-1,state2)+sta[i]; 37 mp.len=l;mp[st]+=(2.0*max(ans1,ans2))/(1.0*l); 38 } 39 if(l&1){ 40 int i=kh; 41 int state=st>>l-i+1<<l-i|st&(1<<l-i)-1; 42 double ans=dfs(l-1,state)+sta[i]; 43 mp.len=l;mp[st]+=ans/(1.0*l); 44 } 45 return mp[st]; 46 } 47 48 int main(){ 49 scanf("%d%d",&n,&k); 50 scanf("%s",s+1); 51 int st=0; 52 for(register signed i=1;i<=n;++i) a[i]=(s[i]=='W'); 53 for(register signed i=1;i<=n;++i) st=st<<1|a[i]; 54 printf("%.7lf",dfs(n,st)); 55 }
T3:it
考場上覺得是個貪心,就和虎那題差很少,其實是個思路很是好的dpevent
首先貪心地考慮,每一個邊頂多被覆蓋一次,由於被覆蓋兩次以上徹底能夠從這條便斷開,那麼會使答案更優。
咱們設$dp[i][0/1]$表示以點i爲根的子樹否/是向上伸,由於他的兩個答案是同時更新的,因此。
而後考慮對於i的兒子y,咱們設兩個二元組w1,w2,w1表示向上伸,w2表示不向上伸。
那麼咱們考慮轉移$w1=min(w1+dp[y][0],w2+dp[y][1])$,$w2=min(w1+dp[y][1],w2+dp[y][0])$
那麼咱們在來考慮怎麼用w1,w2進行轉移。
若是他這條邊不翻轉,那麼能不反轉就不反轉,因此$dp[x][1]=(INF,INF)$,$dp[x][0]=min(w2,(w1.first+1,w1.second))$
若是必須反轉的話,那麼同理$dp[x][0]=(INF,INF)$,$dp[x][1]=min((w1.first,w1.second+1),(w2.first+1,w2.second+1))$
最後答案就是$dp[1][0].first/2$和$dp[1][0].second$
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=3e5+10,INF=1e9+10; 4 int first[N],nex[N<<1],to[N<<1],edge[N<<1],tot; 5 void add(int a,int b,int c){ 6 to[++tot]=b,nex[tot]=first[a],first[a]=tot,edge[tot]=c; 7 } 8 pair<int ,int> min(pair<int ,int> a,pair<int ,int > b){ 9 return a<b?a:b; 10 } 11 pair<int ,int> add(pair<int,int> a,pair<int ,int> b){ 12 return make_pair(a.first+b.first,a.second+b.second); 13 } 14 pair<int ,int> dp[N][2];//0 not up 1 up 15 void dfs(int x,int fa,int ed){ 16 pair<int ,int > p,q; 17 p=make_pair(INF,INF);//up 18 q=make_pair(0,0);//not up 19 pair<int ,int> tmp1,tmp2;//p q; 20 for(int i=first[x];i;i=nex[i]){ 21 int y=to[i]; 22 if(y==fa) continue; 23 dfs(y,x,edge[i]); 24 tmp1=min(add(p,dp[y][0]),add(q,dp[y][1])); 25 tmp2=min(add(q,dp[y][0]),add(p,dp[y][1])); 26 p=make_pair(tmp1.first,tmp1.second); 27 q=make_pair(tmp2.first,tmp2.second); 28 } 29 if(ed==1||ed==2){//bi fan 30 dp[x][1]=min(make_pair(p.first,p.second+1),make_pair(q.first+1,q.second+1)); 31 }else dp[x][1]=make_pair(INF,INF); 32 if(ed==0||ed==2){//bu fan 33 dp[x][0]=min(q,make_pair(p.first+1,p.second)); 34 }else dp[x][0]=make_pair(INF,INF); 35 } 36 37 int main(){ 38 int n; 39 scanf("%d",&n); 40 for(int i=1;i<n;++i){ 41 int a,b,c,d; 42 scanf("%d%d%d%d",&a,&b,&c,&d); 43 int opt; 44 if(d==2) opt=2; 45 else if(c^d) opt=1; 46 else opt=0; 47 add(a,b,opt); 48 add(b,a,opt); 49 } 50 dfs(1,0,2); 51 printf("%d %d",dp[1][0].first>>1,dp[1][0].second); 52 }